mirror of
https://github.com/adambard/learnxinyminutes-docs.git
synced 2025-04-26 15:13:56 +00:00
Merge branch 'adambard:master' into OKEAMAH-patch-1
This commit is contained in:
commit
30b2cc8c19
67
.gitattributes
vendored
67
.gitattributes
vendored
@ -1,65 +1,2 @@
|
||||
asciidoc*.html.markdown linguist-language=AsciiDoc
|
||||
angularjs*.html.markdown linguist-language=JavaScript
|
||||
bash*.html.markdown linguist-language=bash
|
||||
bf.html.markdown linguist-language=Brainfuck
|
||||
bf-*.html.markdown linguist-language=Brainfuck
|
||||
c-*.html.markdown linguist-language=C
|
||||
c.html.markdown linguist-language=C
|
||||
c++*.html.markdown linguist-language=C++
|
||||
chapel*.html.markdown linguist-language=Chapel
|
||||
clojure*.html.markdown linguist-language=Clojure
|
||||
cmake*.html.markdown linguist-language=CMake
|
||||
coffeescript*.html.markdown linguist-language=CoffeeScript
|
||||
coldfusion*.html.markdown linguist-language=ColdFusion
|
||||
common-lisp*.html.markdown linguist-language=lisp
|
||||
compojure*.html.markdown linguist-language=Clojure
|
||||
csharp*.html.markdown linguist-language=C#
|
||||
css*.html.markdown linguist-language=CSS
|
||||
d.html.markdown linguist-language=D
|
||||
d-*.html.markdown linguist-language=D
|
||||
dart*.html.markdown linguist-language=Dart
|
||||
edn*.html.markdown linguist-language=edn
|
||||
elisp*.html.markdown linguist-language=elisp
|
||||
elixir*.html.markdown linguist-language=Elixir
|
||||
elm*.html.markdown linguist-language=Elm
|
||||
erlang*.html.markdown linguist-language=Erlang
|
||||
factor*.html.markdown linguist-language=Factor
|
||||
forth*.html.markdown linguist-language=Forth
|
||||
fortran*.html.markdown linguist-language=FORTRAN
|
||||
fsharp*.html.markdown linguist-language=fsharp
|
||||
go.html.markdown linguist-language=Go
|
||||
go-*.html.markdown linguist-language=Go
|
||||
groovy*.html.markdown linguist-language=Groovy
|
||||
hack*.html.markdown linguist-language=Hack
|
||||
haml*.html.markdown linguist-language=Haml
|
||||
haskell*.html.markdown linguist-language=Haskell
|
||||
haxe*.html.markdown linguist-language=Haxe
|
||||
html*.html.markdown linguist-language=HTML
|
||||
hy.html.markdown linguist-language=Hy
|
||||
hy-*.html.markdown linguist-language=Hy
|
||||
inform7*.html.markdown linguist-language=inform7
|
||||
java.html.markdown linguist-language=Java
|
||||
java-*.html.markdown linguist-language=Java
|
||||
javascript*.html.markdown linguist-language=JavaScript
|
||||
jquery*.html.markdown linguist-language=JavaScript
|
||||
json*.html.markdown linguist-language=JSON
|
||||
julia*.html.markdown linguist-language=Julia
|
||||
kotlin*.html.markdown linguist-language=Kotlin
|
||||
latex*.html.markdown linguist-language=latex
|
||||
less*.html.markdown linguist-language=Less
|
||||
livescript*.html.markdown linguist-language=LiveScript
|
||||
logtalk*.html.markdown linguist-language=Logtalk
|
||||
lua*.html.markdown linguist-language=Lua
|
||||
make*.html.markdown linguist-language=Makefile
|
||||
markdown*.html.markdown linguist-language=Markdown
|
||||
matlab*.html.markdown linguist-language=MATLAB
|
||||
nim*.html.markdown linguist-language=Nimrod
|
||||
nix*.html.markdown linguist-language=Nix
|
||||
objective-c*.html.markdown linguist-language=Objective-C
|
||||
ocaml*.html.markdown linguist-language=OCaml
|
||||
paren*.html.markdown linguist-language=lisp
|
||||
pcre*.html.markdown linguist-language=Perl
|
||||
perl.html.markdown linguist-language=Perl
|
||||
perl-*.html.markdown linguist-language=Perl
|
||||
raku*.html.markdown linguist-language=Perl6
|
||||
ruby*.html.markdown linguist-language=Ruby
|
||||
*.html.markdown linguist-language=Markdown linguist-detectable
|
||||
file.html.erb linguist-vendored
|
||||
|
17
.github/workflows/build.yml
vendored
Normal file
17
.github/workflows/build.yml
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
name: Trigger site build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, master]
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'push' && github.repository_owner == 'adambard'
|
||||
steps:
|
||||
- name: Trigger site build
|
||||
uses: peter-evans/repository-dispatch@v3
|
||||
with:
|
||||
token: ${{ secrets.PAT_LEARNXINYMINUTES_SITE }}
|
||||
repository: adambard/learnxinyminutes-site
|
||||
event-type: doc-update
|
18
.github/workflows/lint.yml
vendored
Normal file
18
.github/workflows/lint.yml
vendored
Normal file
@ -0,0 +1,18 @@
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
pull_request:
|
||||
branches: [master]
|
||||
|
||||
jobs:
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ruby/setup-ruby@v1
|
||||
with:
|
||||
ruby-version: '3.2'
|
||||
- run: gem install mdl
|
||||
- run: mdl . --ignore-front-matter -r MD003,MD011,MD023,MD027,MD028,MD035,MD037,MD038,MD039,MD047
|
@ -1,3 +0,0 @@
|
||||
language: ruby
|
||||
rvm:
|
||||
- 2.2
|
@ -34,7 +34,7 @@ review them more effectively and/or individually.
|
||||
* **Use UTF-8**
|
||||
* For translations (or EN articles with non-ASCII characters) please ensure
|
||||
your file is UTF-8 encoded.
|
||||
* Try to leave out the byte-order-mark at the start of the file (in Vim, use
|
||||
* Leave out the byte-order-mark (BOM) at the start of the file (in Vim, use
|
||||
`:set nobomb`).
|
||||
* You can check if the file contains a BOM on Linux/Unix systems by running
|
||||
`file language.html.markdown` You will see this if it uses a BOM:
|
||||
@ -58,7 +58,7 @@ Other fields:
|
||||
*tool* or *Algorithms & Data Structures*. Defaults to *language* if omitted.
|
||||
* **filename**: The filename for this article's code. It will be fetched, mashed
|
||||
together, and made downloadable.
|
||||
* For non-English articles, *filename* should have a language-specific
|
||||
* For non-English articles, *filename* should have a language-specific
|
||||
suffix.
|
||||
* **lang**: For translations, the human language this article is in. For
|
||||
categorization, mostly.
|
||||
@ -76,7 +76,12 @@ lang: ep-ep
|
||||
*--
|
||||
```
|
||||
|
||||
### Should I add myself as a Contributor?
|
||||
### Syntax highlighter
|
||||
|
||||
[Pygments](https://pygments.org/languages/) is used for syntax highlighting through
|
||||
[pygments.rb](https://github.com/pygments/pygments.rb).
|
||||
|
||||
### Should I add myself as a contributor?
|
||||
|
||||
If you want to add yourself to contributors, keep in mind that contributors get
|
||||
equal billing, and the first contributor usually wrote the whole article. Please
|
||||
|
5
Gemfile
5
Gemfile
@ -1,5 +0,0 @@
|
||||
source 'http://rubygems.org'
|
||||
group :test do
|
||||
gem 'rake'
|
||||
gem 'charlock_holmes'
|
||||
end
|
15
Gemfile.lock
15
Gemfile.lock
@ -1,15 +0,0 @@
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
specs:
|
||||
charlock_holmes (0.7.3)
|
||||
rake (12.0.0)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
||||
DEPENDENCIES
|
||||
charlock_holmes
|
||||
rake
|
||||
|
||||
BUNDLED WITH
|
||||
1.13.7
|
@ -1,7 +1,5 @@
|
||||
# [Learn X in Y minutes][1]
|
||||
|
||||
[](https://travis-ci.org/adambard/learnxinyminutes-docs)
|
||||
|
||||
Whirlwind tours of (several, hopefully many someday) popular and
|
||||
ought-to-be-more-popular programming languages, presented as valid, commented
|
||||
code and explained as they go.
|
||||
|
23
Rakefile
23
Rakefile
@ -1,23 +0,0 @@
|
||||
task default: %w[encoding yaml return_code]
|
||||
$failure = 0
|
||||
task :encoding do
|
||||
begin
|
||||
ruby 'tests/encoding.rb'
|
||||
rescue Exception => msg
|
||||
puts msg
|
||||
$failure += 1
|
||||
end
|
||||
end
|
||||
task :yaml do
|
||||
begin
|
||||
ruby 'tests/yaml.rb'
|
||||
rescue Exception => msg
|
||||
puts msg
|
||||
$failure += 1
|
||||
end
|
||||
end
|
||||
task :return_code do
|
||||
if $failure != 0
|
||||
raise "Failed #{$failure} tests!!"
|
||||
end
|
||||
end
|
@ -2,10 +2,10 @@
|
||||
language: Ada
|
||||
filename: learn.ada
|
||||
contributors:
|
||||
["Luke A. Guest", "https://github.com/Lucretia"]
|
||||
["Fernando Oleo Blanco", "https://github.com/Irvise"]
|
||||
["Fabien Chouteau", "https://github.com/Fabien-Chouteau"]
|
||||
["Manuel", "https://github.com/mgrojo"]
|
||||
- ["Luke A. Guest", "https://github.com/Lucretia"]
|
||||
- ["Fernando Oleo Blanco", "https://github.com/Irvise"]
|
||||
- ["Fabien Chouteau", "https://github.com/Fabien-Chouteau"]
|
||||
- ["Manuel", "https://github.com/mgrojo"]
|
||||
---
|
||||
|
||||
Ada is a strong statically typed imperative, [object-oriented](https://ada-lang.io/docs/arm/AA-3/AA-3.9), [real-time](https://ada-lang.io/docs/arm/AA-D), [parallel](https://ada-lang.io/docs/arm/AA-9) and [distributed](https://ada-lang.io/docs/arm/AA-9) programming language from the Pascal/Algol family of languages, but nowadays, it only has a passing resemblance to Pascal, with the only remnants left being the ```begin/end``` keyword pair, the ```:=``` assignment symbol, records and ```if/case``` control statement structures.
|
||||
|
@ -1,212 +1,219 @@
|
||||
---
|
||||
category: tool
|
||||
tool: amd
|
||||
contributors:
|
||||
- ["Frederik Ring", "https://github.com/m90"]
|
||||
filename: learnamd.js
|
||||
---
|
||||
|
||||
## Getting Started with AMD
|
||||
|
||||
The **Asynchronous Module Definition** API specifies a mechanism for defining
|
||||
JavaScript modules such that the module and its dependencies can be asynchronously
|
||||
loaded. This is particularly well suited for the browser environment where
|
||||
synchronous loading of modules incurs performance, usability, debugging, and
|
||||
cross-domain access problems.
|
||||
|
||||
### Basic concept
|
||||
```javascript
|
||||
// The basic AMD API consists of nothing but two methods: `define` and `require`
|
||||
// and is all about module definition and consumption:
|
||||
// `define(id?, dependencies?, factory)` defines a module
|
||||
// `require(dependencies, callback)` imports a set of dependencies and
|
||||
// consumes them in the passed callback
|
||||
|
||||
// Let's start by using define to define a new named module
|
||||
// that has no dependencies. We'll do so by passing a name
|
||||
// and a factory function to define:
|
||||
define('awesomeAMD', function(){
|
||||
var isAMDAwesome = function(){
|
||||
return true;
|
||||
};
|
||||
// The return value of a module's factory function is
|
||||
// what other modules or require calls will receive when
|
||||
// requiring our `awesomeAMD` module.
|
||||
// The exported value can be anything, (constructor) functions,
|
||||
// objects, primitives, even undefined (although that won't help too much).
|
||||
return isAMDAwesome;
|
||||
});
|
||||
|
||||
// Now, let's define another module that depends upon our `awesomeAMD` module.
|
||||
// Notice that there's an additional argument defining our
|
||||
// module's dependencies now:
|
||||
define('loudmouth', ['awesomeAMD'], function(awesomeAMD){
|
||||
// dependencies will be passed to the factory's arguments
|
||||
// in the order they are specified
|
||||
var tellEveryone = function(){
|
||||
if (awesomeAMD()){
|
||||
alert('This is sOoOo rad!');
|
||||
} else {
|
||||
alert('Pretty dull, isn\'t it?');
|
||||
}
|
||||
};
|
||||
return tellEveryone;
|
||||
});
|
||||
|
||||
// As we do know how to use define now, let's use `require` to
|
||||
// kick off our program. `require`'s signature is `(arrayOfDependencies, callback)`.
|
||||
require(['loudmouth'], function(loudmouth){
|
||||
loudmouth();
|
||||
});
|
||||
|
||||
// To make this tutorial run code, let's implement a very basic
|
||||
// (non-asynchronous) version of AMD right here on the spot:
|
||||
function define(name, deps, factory){
|
||||
// notice how modules without dependencies are handled
|
||||
define[name] = require(factory ? deps : [], factory || deps);
|
||||
}
|
||||
|
||||
function require(deps, callback){
|
||||
var args = [];
|
||||
// first let's retrieve all the dependencies needed
|
||||
// by the require call
|
||||
for (var i = 0; i < deps.length; i++){
|
||||
args[i] = define[deps[i]];
|
||||
}
|
||||
// satisfy all the callback's dependencies
|
||||
return callback.apply(null, args);
|
||||
}
|
||||
// you can see this code in action here: http://jsfiddle.net/qap949pd/
|
||||
```
|
||||
|
||||
### Real-world usage with require.js
|
||||
|
||||
In contrast to the introductory example, `require.js` (the most popular AMD library) actually implements the **A** in **AMD**, enabling you to load modules and their dependencies asynchronously via XHR:
|
||||
|
||||
```javascript
|
||||
/* file: app/main.js */
|
||||
require(['modules/someClass'], function(SomeClass){
|
||||
// the callback is deferred until the dependency is loaded
|
||||
var thing = new SomeClass();
|
||||
});
|
||||
console.log('So here we are, waiting!'); // this will run first
|
||||
```
|
||||
|
||||
By convention, you usually store one module in one file. `require.js` can resolve module names based on file paths, so you don't have to name your modules, but can simply reference them using their location. In the example `someClass` is assumed to be in the `modules` folder, relative to your configuration's `baseUrl`:
|
||||
|
||||
* app/
|
||||
* main.js
|
||||
* modules/
|
||||
* someClass.js
|
||||
* someHelpers.js
|
||||
* ...
|
||||
* daos/
|
||||
* things.js
|
||||
* ...
|
||||
|
||||
This means we can define `someClass` without specifying a module id:
|
||||
|
||||
```javascript
|
||||
/* file: app/modules/someClass.js */
|
||||
define(['daos/things', 'modules/someHelpers'], function(thingsDao, helpers){
|
||||
// module definition, of course, will also happen asynchronously
|
||||
function SomeClass(){
|
||||
this.method = function(){/**/};
|
||||
// ...
|
||||
}
|
||||
return SomeClass;
|
||||
});
|
||||
```
|
||||
To alter the default path mapping behavior use `requirejs.config(configObj)` in your `main.js`:
|
||||
|
||||
```javascript
|
||||
/* file: main.js */
|
||||
requirejs.config({
|
||||
baseUrl : 'app',
|
||||
paths : {
|
||||
// you can also load modules from other locations
|
||||
jquery : '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
|
||||
coolLibFromBower : '../bower_components/cool-lib/coollib'
|
||||
}
|
||||
});
|
||||
require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolLib, helpers){
|
||||
// a `main` file needs to call require at least once,
|
||||
// otherwise no code will ever run
|
||||
coolLib.doFancyStuffWith(helpers.transform($('#foo')));
|
||||
});
|
||||
```
|
||||
`require.js`-based apps will usually have a single entry point (`main.js`) that is passed to the `require.js` script tag as a data-attribute. It will be automatically loaded and executed on pageload:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>A hundred script tags? Never again!</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="require.js" data-main="app/main"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### Optimizing a whole project using r.js
|
||||
|
||||
Many people prefer using AMD for sane code organization during development, but still want to ship a single script file in production instead of performing hundreds of XHRs on page load.
|
||||
|
||||
`require.js` comes with a script called `r.js` (that you will probably run in node.js, although Rhino is supported too) that can analyse your project's dependency graph, and build a single file containing all your modules (properly named), minified and ready for consumption.
|
||||
|
||||
Install it using `npm`:
|
||||
```shell
|
||||
$ npm install requirejs -g
|
||||
```
|
||||
|
||||
Now you can feed it with a configuration file:
|
||||
```shell
|
||||
$ r.js -o app.build.js
|
||||
```
|
||||
|
||||
For our above example the configuration might look like:
|
||||
```javascript
|
||||
/* file : app.build.js */
|
||||
({
|
||||
name : 'main', // name of the entry point
|
||||
out : 'main-built.js', // name of the file to write the output to
|
||||
baseUrl : 'app',
|
||||
paths : {
|
||||
// `empty:` tells r.js that this should still be loaded from the CDN, using
|
||||
// the location specified in `main.js`
|
||||
jquery : 'empty:',
|
||||
coolLibFromBower : '../bower_components/cool-lib/coollib'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
To use the built file in production, simply swap `data-main`:
|
||||
```html
|
||||
<script src="require.js" data-main="app/main-built"></script>
|
||||
```
|
||||
|
||||
An incredibly detailed [overview of build options](https://github.com/jrburke/r.js/blob/master/build/example.build.js) is available in the GitHub repo.
|
||||
|
||||
### Topics not covered in this tutorial
|
||||
* [Loader plugins / transforms](http://requirejs.org/docs/plugins.html)
|
||||
* [CommonJS style loading and exporting](http://requirejs.org/docs/commonjs.html)
|
||||
* [Advanced configuration](http://requirejs.org/docs/api.html#config)
|
||||
* [Shim configuration (loading non-AMD modules)](http://requirejs.org/docs/api.html#config-shim)
|
||||
* [CSS loading and optimizing with require.js](http://requirejs.org/docs/optimization.html#onecss)
|
||||
* [Using almond.js for builds](https://github.com/jrburke/almond)
|
||||
|
||||
### Further reading:
|
||||
|
||||
* [Official Spec](https://github.com/amdjs/amdjs-api/wiki/AMD)
|
||||
* [Why AMD?](http://requirejs.org/docs/whyamd.html)
|
||||
* [Universal Module Definition](https://github.com/umdjs/umd)
|
||||
|
||||
### Implementations:
|
||||
|
||||
* [require.js](http://requirejs.org)
|
||||
* [dojo toolkit](http://dojotoolkit.org/documentation/tutorials/1.9/modules/)
|
||||
* [cujo.js](http://cujojs.com/)
|
||||
* [curl.js](https://github.com/cujojs/curl)
|
||||
* [lsjs](https://github.com/zazl/lsjs)
|
||||
* [mmd](https://github.com/alexlawrence/mmd)
|
||||
---
|
||||
category: tool
|
||||
tool: amd
|
||||
contributors:
|
||||
- ["Frederik Ring", "https://github.com/m90"]
|
||||
filename: learnamd.js
|
||||
---
|
||||
|
||||
## Getting Started with AMD
|
||||
|
||||
The **Asynchronous Module Definition** API specifies a mechanism for defining
|
||||
JavaScript modules such that the module and its dependencies can be asynchronously
|
||||
loaded. This is particularly well suited for the browser environment where
|
||||
synchronous loading of modules incurs performance, usability, debugging, and
|
||||
cross-domain access problems.
|
||||
|
||||
### Basic concept
|
||||
|
||||
```javascript
|
||||
// The basic AMD API consists of nothing but two methods: `define` and `require`
|
||||
// and is all about module definition and consumption:
|
||||
// `define(id?, dependencies?, factory)` defines a module
|
||||
// `require(dependencies, callback)` imports a set of dependencies and
|
||||
// consumes them in the passed callback
|
||||
|
||||
// Let's start by using define to define a new named module
|
||||
// that has no dependencies. We'll do so by passing a name
|
||||
// and a factory function to define:
|
||||
define('awesomeAMD', function(){
|
||||
var isAMDAwesome = function(){
|
||||
return true;
|
||||
};
|
||||
// The return value of a module's factory function is
|
||||
// what other modules or require calls will receive when
|
||||
// requiring our `awesomeAMD` module.
|
||||
// The exported value can be anything, (constructor) functions,
|
||||
// objects, primitives, even undefined (although that won't help too much).
|
||||
return isAMDAwesome;
|
||||
});
|
||||
|
||||
// Now, let's define another module that depends upon our `awesomeAMD` module.
|
||||
// Notice that there's an additional argument defining our
|
||||
// module's dependencies now:
|
||||
define('loudmouth', ['awesomeAMD'], function(awesomeAMD){
|
||||
// dependencies will be passed to the factory's arguments
|
||||
// in the order they are specified
|
||||
var tellEveryone = function(){
|
||||
if (awesomeAMD()){
|
||||
alert('This is sOoOo rad!');
|
||||
} else {
|
||||
alert('Pretty dull, isn\'t it?');
|
||||
}
|
||||
};
|
||||
return tellEveryone;
|
||||
});
|
||||
|
||||
// As we do know how to use define now, let's use `require` to
|
||||
// kick off our program. `require`'s signature is `(arrayOfDependencies, callback)`.
|
||||
require(['loudmouth'], function(loudmouth){
|
||||
loudmouth();
|
||||
});
|
||||
|
||||
// To make this tutorial run code, let's implement a very basic
|
||||
// (non-asynchronous) version of AMD right here on the spot:
|
||||
function define(name, deps, factory){
|
||||
// notice how modules without dependencies are handled
|
||||
define[name] = require(factory ? deps : [], factory || deps);
|
||||
}
|
||||
|
||||
function require(deps, callback){
|
||||
var args = [];
|
||||
// first let's retrieve all the dependencies needed
|
||||
// by the require call
|
||||
for (var i = 0; i < deps.length; i++){
|
||||
args[i] = define[deps[i]];
|
||||
}
|
||||
// satisfy all the callback's dependencies
|
||||
return callback.apply(null, args);
|
||||
}
|
||||
// you can see this code in action here: http://jsfiddle.net/qap949pd/
|
||||
```
|
||||
|
||||
### Real-world usage with require.js
|
||||
|
||||
In contrast to the introductory example, `require.js` (the most popular AMD library) actually implements the **A** in **AMD**, enabling you to load modules and their dependencies asynchronously via XHR:
|
||||
|
||||
```javascript
|
||||
/* file: app/main.js */
|
||||
require(['modules/someClass'], function(SomeClass){
|
||||
// the callback is deferred until the dependency is loaded
|
||||
var thing = new SomeClass();
|
||||
});
|
||||
console.log('So here we are, waiting!'); // this will run first
|
||||
```
|
||||
|
||||
By convention, you usually store one module in one file. `require.js` can resolve module names based on file paths, so you don't have to name your modules, but can simply reference them using their location. In the example `someClass` is assumed to be in the `modules` folder, relative to your configuration's `baseUrl`:
|
||||
|
||||
* app/
|
||||
* main.js
|
||||
* modules/
|
||||
* someClass.js
|
||||
* someHelpers.js
|
||||
* ...
|
||||
* daos/
|
||||
* things.js
|
||||
* ...
|
||||
|
||||
This means we can define `someClass` without specifying a module id:
|
||||
|
||||
```javascript
|
||||
/* file: app/modules/someClass.js */
|
||||
define(['daos/things', 'modules/someHelpers'], function(thingsDao, helpers){
|
||||
// module definition, of course, will also happen asynchronously
|
||||
function SomeClass(){
|
||||
this.method = function(){/**/};
|
||||
// ...
|
||||
}
|
||||
return SomeClass;
|
||||
});
|
||||
```
|
||||
|
||||
To alter the default path mapping behavior use `requirejs.config(configObj)` in your `main.js`:
|
||||
|
||||
```javascript
|
||||
/* file: main.js */
|
||||
requirejs.config({
|
||||
baseUrl : 'app',
|
||||
paths : {
|
||||
// you can also load modules from other locations
|
||||
jquery : '//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min',
|
||||
coolLibFromBower : '../bower_components/cool-lib/coollib'
|
||||
}
|
||||
});
|
||||
require(['jquery', 'coolLibFromBower', 'modules/someHelpers'], function($, coolLib, helpers){
|
||||
// a `main` file needs to call require at least once,
|
||||
// otherwise no code will ever run
|
||||
coolLib.doFancyStuffWith(helpers.transform($('#foo')));
|
||||
});
|
||||
```
|
||||
|
||||
`require.js`-based apps will usually have a single entry point (`main.js`) that is passed to the `require.js` script tag as a data-attribute. It will be automatically loaded and executed on pageload:
|
||||
|
||||
```html
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>A hundred script tags? Never again!</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="require.js" data-main="app/main"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
### Optimizing a whole project using r.js
|
||||
|
||||
Many people prefer using AMD for sane code organization during development, but still want to ship a single script file in production instead of performing hundreds of XHRs on page load.
|
||||
|
||||
`require.js` comes with a script called `r.js` (that you will probably run in node.js, although Rhino is supported too) that can analyse your project's dependency graph, and build a single file containing all your modules (properly named), minified and ready for consumption.
|
||||
|
||||
Install it using `npm`:
|
||||
|
||||
```shell
|
||||
$ npm install requirejs -g
|
||||
```
|
||||
|
||||
Now you can feed it with a configuration file:
|
||||
|
||||
```shell
|
||||
$ r.js -o app.build.js
|
||||
```
|
||||
|
||||
For our above example the configuration might look like:
|
||||
|
||||
```javascript
|
||||
/* file : app.build.js */
|
||||
({
|
||||
name : 'main', // name of the entry point
|
||||
out : 'main-built.js', // name of the file to write the output to
|
||||
baseUrl : 'app',
|
||||
paths : {
|
||||
// `empty:` tells r.js that this should still be loaded from the CDN, using
|
||||
// the location specified in `main.js`
|
||||
jquery : 'empty:',
|
||||
coolLibFromBower : '../bower_components/cool-lib/coollib'
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
To use the built file in production, simply swap `data-main`:
|
||||
|
||||
```html
|
||||
<script src="require.js" data-main="app/main-built"></script>
|
||||
```
|
||||
|
||||
An incredibly detailed [overview of build options](https://github.com/jrburke/r.js/blob/master/build/example.build.js) is available in the GitHub repo.
|
||||
|
||||
### Topics not covered in this tutorial
|
||||
* [Loader plugins / transforms](http://requirejs.org/docs/plugins.html)
|
||||
* [CommonJS style loading and exporting](http://requirejs.org/docs/commonjs.html)
|
||||
* [Advanced configuration](http://requirejs.org/docs/api.html#config)
|
||||
* [Shim configuration (loading non-AMD modules)](http://requirejs.org/docs/api.html#config-shim)
|
||||
* [CSS loading and optimizing with require.js](http://requirejs.org/docs/optimization.html#onecss)
|
||||
* [Using almond.js for builds](https://github.com/jrburke/almond)
|
||||
|
||||
### Further reading:
|
||||
|
||||
* [Official Spec](https://github.com/amdjs/amdjs-api/wiki/AMD)
|
||||
* [Why AMD?](http://requirejs.org/docs/whyamd.html)
|
||||
* [Universal Module Definition](https://github.com/umdjs/umd)
|
||||
|
||||
### Implementations:
|
||||
|
||||
* [require.js](http://requirejs.org)
|
||||
* [dojo toolkit](http://dojotoolkit.org/documentation/tutorials/1.9/modules/)
|
||||
* [cujo.js](http://cujojs.com/)
|
||||
* [curl.js](https://github.com/cujojs/curl)
|
||||
* [lsjs](https://github.com/zazl/lsjs)
|
||||
* [mmd](https://github.com/alexlawrence/mmd)
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
category: tool
|
||||
tool: AngularJS
|
||||
category: framework
|
||||
framework: AngularJS
|
||||
contributors:
|
||||
- ["Walter Cordero", "http://waltercordero.com"]
|
||||
filename: learnangular.html
|
||||
|
@ -632,7 +632,7 @@ fact_caching_timeout = 86400
|
||||
```
|
||||
|
||||
I like to use `jsonfile` as my backend. It allows to use another project
|
||||
`ansible-cmdb` [(project on github)](https://github.com/fboender/ansible-cmdb) that generates a HTML page of your inventory
|
||||
`ansible-cmdb` [(project on GitHub)](https://github.com/fboender/ansible-cmdb) that generates a HTML page of your inventory
|
||||
resources. A nice 'free' addition!
|
||||
|
||||
### Debugging ansible [chapter in progress]
|
||||
|
69
apl.html.markdown
Normal file
69
apl.html.markdown
Normal file
@ -0,0 +1,69 @@
|
||||
---
|
||||
language: APL
|
||||
contributors:
|
||||
- ["nooodl", "https://github.com/nooodl"]
|
||||
filename: learnapl.apl
|
||||
---
|
||||
|
||||
```apl
|
||||
⍝ Comments in APL are prefixed by ⍝.
|
||||
|
||||
⍝ A list of numbers. (¯ is negative)
|
||||
2 3e7 ¯4 50.3
|
||||
|
||||
⍝ An expression, showing some functions. In APL, there's
|
||||
⍝ no order of operations: everything is parsed right-to-
|
||||
⍝ left. This is equal to 5 + (4 × (2 ÷ (5 - 3))) = 9:
|
||||
5 + 4 × 2 ÷ 5 - 3 ⍝ 9
|
||||
|
||||
⍝ These functions work on lists, too:
|
||||
1 2 3 4 × 5 ⍝ 5 10 15 20
|
||||
1 2 3 4 × 5 6 7 8 ⍝ 5 12 21 32
|
||||
|
||||
⍝ All functions have single-argument and dual-argument
|
||||
⍝ meanings. For example, "×" applied to two arguments
|
||||
⍝ means multiply, but when applied to only a right-hand
|
||||
⍝ side, it returns the sign:
|
||||
|
||||
× ¯4 ¯2 0 2 4 ⍝ ¯1 ¯1 0 1 1
|
||||
|
||||
⍝ Values can be compared using these operators (1 means
|
||||
⍝ "true", 0 means "false"):
|
||||
|
||||
10 20 30 = 10 20 99 ⍝ 1 1 0
|
||||
|
||||
10 20 30 < 10 20 99 ⍝ 0 0 1
|
||||
|
||||
⍝ "⍳n" returns a vector containing the first n naturals.
|
||||
⍝ Matrices can be constructed using ⍴ (reshape):
|
||||
4 3 ⍴ ⍳5 ⍝ 0 1 2
|
||||
⍝ 3 4 0
|
||||
⍝ 1 2 3
|
||||
⍝ 4 0 1
|
||||
|
||||
⍝ Single-argument ⍴ gives you the dimensions back:
|
||||
⍴ 4 3 ⍴ ⍳5 ⍝ 4 3
|
||||
|
||||
⍝ Values can be stored using ←. Let's calculate the mean
|
||||
⍝ value of a vector of numbers:
|
||||
A ← 10 60 55 23
|
||||
|
||||
⍝ Sum of elements of A (/ is reduce):
|
||||
+/A ⍝ 148
|
||||
|
||||
⍝ Length of A:
|
||||
⍴A ⍝ 4
|
||||
|
||||
⍝ Mean:
|
||||
(+/A) ÷ (⍴A) ⍝ 37
|
||||
|
||||
⍝ We can define this as a function using {} and ⍵:
|
||||
mean ← {(+/⍵)÷⍴⍵}
|
||||
mean A ⍝ 37
|
||||
```
|
||||
|
||||
## Further Reading
|
||||
|
||||
- [APL Wiki](https://aplwiki.com/)
|
||||
- An older version of APL book by the creator: [Kenneth Iverson - A Programming Language](https://www.softwarepreservation.org/projects/apl/Books/APROGRAMMING%20LANGUAGE/view)
|
||||
- Additional Books: [APL Books](https://aplwiki.com/wiki/Books)
|
@ -107,7 +107,6 @@ HTML اختصار ل HyperText Markup Language، أي "لغة ترميز الن
|
||||
<td>الصف الثاني، العمود الأول</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
```
|
||||
|
||||
## الاستعمال
|
||||
|
@ -17,12 +17,9 @@ filename: learnpython-ar.py
|
||||
لقد أُنشئت لغة البايثون بواسطة جايدو ڤان روسم في بداية التسعينات. هي الأن أحد أشهر اللغات الموجودة.
|
||||
لقد أحببت لغة البايثون بسبب وضوحها. هي في الأساس عبارة عن سودوكود قابل للتنفيذ.
|
||||
|
||||
ردود أفعالكم عن المقال مُقدرة بشدة. يمكنكم التواصل مع الكاتب الاساسي من خلال [@louiedinh](http://twitter.com/louiedinh) أو louiedinh [at] [google's email service]
|
||||
|
||||
ملحوظة: هذا المقال يُطبق على بايثون 3 فقط. راجع المقال [هنا](http://learnxinyminutes.com/docs/pythonlegacy/) إذا أردت تعلم لغة البايثون نسخة 2.7 الأقدم
|
||||
|
||||
```python
|
||||
|
||||
# تعليق من سطر واحد يبدأ برمز الرقم.
|
||||
|
||||
""" يمكن كتابة تعليق يتكون من أكثر من سطر
|
||||
@ -1006,14 +1003,11 @@ print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
|
||||
### مجانا عبر الانترنت
|
||||
|
||||
* [أتمتتة المهمات المُملة عبر بايثون](https://automatetheboringstuff.com)
|
||||
* [أفكار لمشروعات بلغة البايثون](http://pythonpracticeprojects.com)
|
||||
* [التوثيقات الرسمية](http://docs.python.org/3/)
|
||||
* [دليل المُسافر لبايثون](http://docs.python-guide.org/en/latest/)
|
||||
* [دورة بايثون](http://www.python-course.eu/index.php)
|
||||
* [أولى الخطوات مع بايثون](https://realpython.com/learn/python-first-steps/)
|
||||
* [قائمة مُختارة من إطارات عمل بايثون الرائعة, المكتبات والبرمجيات](https://github.com/vinta/awesome-python)
|
||||
* [ثلاثون خاصية وخدعة للغة البايثون ربما لم تعرف بها](http://sahandsaba.com/thirty-python-language-features-and-tricks-you-may-not-know.html)
|
||||
* [الدليل الرسمي لنمط البايثون](https://www.python.org/dev/peps/pep-0008/)
|
||||
* [الدليل الرسمي لنمط البايثون](https://peps.python.org/pep-0008/)
|
||||
* [بايثون 3 دوائر علوم الحاسب](http://cscircles.cemc.uwaterloo.ca/)
|
||||
* [غُص في بايثون 3](http://www.diveintopython3.net/index.html)
|
||||
* [دورة سريعة في البايثون للعلماء](http://nbviewer.jupyter.org/gist/anonymous/5924718)
|
||||
|
@ -27,9 +27,9 @@ QUIT , EXIT
|
||||
في الامثلة بالأسفل تعتمدالعديد من الأوامرأن قاعدة بيانات الموظفين
|
||||
[MySQL employee sample database](https://dev.mysql.com/doc/employee/en/)
|
||||
الموجودة على
|
||||
[github](https://github.com/datacharmer/test_db)
|
||||
[GitHub](https://github.com/datacharmer/test_db)
|
||||
قد تم تحميلها مسبقا. الملفات على
|
||||
github
|
||||
GitHub
|
||||
هي مجموعة من الاوامر تشبه الموجودة بالاسفل و تقوم الأوامر بإنشاء الجدوال وإدخال بيانات مجموعة من الموظفين المتخيلين في شركة. تعتمد الأوامر المستخدمة في هذا البرنامج على نسخة
|
||||
SQL
|
||||
التي تستخدمها،
|
||||
@ -125,6 +125,7 @@ DELETE FROM tablename1;
|
||||
-- تماما tablename1 إزالة جدول
|
||||
DROP TABLE tablename1;
|
||||
```
|
||||
|
||||
<div dir="rtl">
|
||||
|
||||
## اقرأ أكثر
|
||||
|
@ -81,7 +81,6 @@ Section Titles
|
||||
==== Level 3 <h4>
|
||||
|
||||
===== Level 4 <h5>
|
||||
|
||||
```
|
||||
|
||||
Lists
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: Assemblyscript
|
||||
language: AssemblyScript
|
||||
contributors:
|
||||
- ["Philippe Vlérick", "https://github.com/pvlerick"]
|
||||
- ["Steve Huguenin-Elie", "https://github.com/StEvUgnIn"]
|
||||
@ -13,7 +13,7 @@ __AssemblyScript__ compiles a variant of __TypeScript__ (basically JavaScript wi
|
||||
This article will focus only on AssemblyScript extra syntax, as opposed to [TypeScript](/docs/typescript) and [JavaScript](/docs/javascript).
|
||||
|
||||
To test AssemblyScript's compiler, head to the
|
||||
[Playground](https://bit.ly/asplayground) where you will be able
|
||||
[Playground](https://www.assemblyscript.org/editor.html#IyFydW50aW1lPXN0dWIKLyoqIENhbGN1bGF0ZXMgdGhlIG4tdGggRmlib25hY2NpIG51bWJlci4gKi8KZXhwb3J0IGZ1bmN0aW9uIGZpYihuOiBpMzIpOiBpMzIgewogIHZhciBhID0gMCwgYiA9IDEKICBpZiAobiA+IDApIHsKICAgIHdoaWxlICgtLW4pIHsKICAgICAgbGV0IHQgPSBhICsgYgogICAgICBhID0gYgogICAgICBiID0gdAogICAgfQogICAgcmV0dXJuIGIKICB9CiAgcmV0dXJuIGEKfQoKIyFodG1sCjx0ZXh0YXJlYSBpZD0ib3V0cHV0IiBzdHlsZT0iaGVpZ2h0OiAxMDAlOyB3aWR0aDogMTAwJSIgcmVhZG9ubHk+PC90ZXh0YXJlYT4KPHNjcmlwdD4KbG9hZGVyLmluc3RhbnRpYXRlKG1vZHVsZV93YXNtLCB7IC8qIGltcG9ydHMgKi8gfSkKICAudGhlbigoeyBleHBvcnRzIH0pID0+IHsKICAgIGNvbnN0IG91dHB1dCA9IGRvY3VtZW50LmdldEVsZW1lbnRCeUlkKCdvdXRwdXQnKQogICAgZm9yIChsZXQgaSA9IDA7IGkgPD0gMTA7ICsraSkgewogICAgICBvdXRwdXQudmFsdWUgKz0gYGZpYigke2l9KSA9ICR7ZXhwb3J0cy5maWIoaSl9XG5gCiAgICB9CiAgfSkKPC9zY3JpcHQ+Cg==) where you will be able
|
||||
to type code, have auto completion and directly see the emitted WebAssembly.
|
||||
|
||||
```ts
|
||||
@ -144,11 +144,11 @@ export namespace Geometry {
|
||||
let s1 = new Geometry.Square(5);
|
||||
|
||||
// Generics
|
||||
// AssemblyScript compiles generics to one concrete method or function per set
|
||||
// of unique contextual type arguments, also known as [monomorphisation].
|
||||
// Implications are that a module only includes and exports concrete functions
|
||||
// for sets of type arguments actually used and that concrete functions can be
|
||||
// shortcutted with [static type checks] at compile time, which turned out to
|
||||
// AssemblyScript compiles generics to one concrete method or function per set
|
||||
// of unique contextual type arguments, also known as [monomorphisation].
|
||||
// Implications are that a module only includes and exports concrete functions
|
||||
// for sets of type arguments actually used and that concrete functions can be
|
||||
// shortcutted with [static type checks] at compile time, which turned out to
|
||||
// be quite useful.
|
||||
// Classes
|
||||
export class Tuple<T1, T2> {
|
||||
@ -193,10 +193,10 @@ let doubles = [0.0, 1.0, 2, 3, 4] // will infer as Array<f64>
|
||||
let bytes1 = [0 as u8, 1, 2, 3, 4] // will infer as Array<u8>
|
||||
let bytes2 = [0, 1, 2, 3, 4] as u8[] // will infer as Array<u8>
|
||||
let bytes3: u8[] = [0, 1, 2, 3, 4] // will infer as Array<u8>
|
||||
|
||||
```
|
||||
|
||||
## Further Reading
|
||||
* [AssemblyScript Official website] (https://www.assemblyscript.org/)
|
||||
* [AssemblyScript source documentation] https://github.com/AssemblyScript/website/tree/main/src)
|
||||
* [Source Code on GitHub] (https://github.com/AssemblyScript/assemblyscript)
|
||||
|
||||
* [AssemblyScript Official website](https://www.assemblyscript.org/)
|
||||
* [AssemblyScript source documentation](https://github.com/AssemblyScript/website/tree/main/src)
|
||||
* [Source Code on GitHub](https://github.com/AssemblyScript/assemblyscript)
|
||||
|
@ -375,7 +375,6 @@ END {
|
||||
if (nlines)
|
||||
print "The average age for " name " is " sum / nlines;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
Further Reading:
|
||||
|
@ -4,7 +4,7 @@ contributors:
|
||||
- ["Btup"]
|
||||
filename: learnbc.bc
|
||||
---
|
||||
```c
|
||||
```bc
|
||||
/*This is a multi-
|
||||
line comment.*/
|
||||
# This is also a (one-line) comment! (in GNU bc).
|
||||
@ -29,27 +29,23 @@ hour = read() /*Input a number*/
|
||||
|
||||
if(hour < 12) { /*Operators are exactly like C.*/
|
||||
print "Good morning\n" /*"print" outputs strings or variables
|
||||
separated by commas.*/
|
||||
separated by commas.*/
|
||||
} else if(hour == 12) {
|
||||
print "Hello\n"
|
||||
/*Escaping sequences start with a \ in a string.
|
||||
In order to make the escaping sequences clearer, here
|
||||
is a simplified list of them that will work in bc:
|
||||
is a simplified list of them that will work in bc:
|
||||
\b: backspace
|
||||
\c: carriage return
|
||||
\n: newline
|
||||
\t: tab
|
||||
\\: backslash*/
|
||||
} else {
|
||||
/*Variables are global by default.*/
|
||||
thisIsGlobal = 5
|
||||
/*You can make a variable local. Use the "auto" keyword in a function.*/
|
||||
print "Good afternoon\n"
|
||||
}
|
||||
|
||||
/*Every variable is pre-set to 0.*/
|
||||
num = blankVariable /*num is set to 0.*/
|
||||
|
||||
/*Like C, only 0 is falsy.*/
|
||||
num = 0
|
||||
if(!num) {print "false\n"}
|
||||
|
||||
/*Unlike C, bc does not have the ?: operators. For example,
|
||||
@ -93,6 +89,7 @@ print a[0], " ", a[1], " ", a[2], " ", a[3], "\n"
|
||||
quit /*Add this line of code to make sure
|
||||
that your program exits. This line of code is optional.*/
|
||||
```
|
||||
|
||||
Enjoy this simple calculator! (Or this programming language, to be exact.)
|
||||
|
||||
This whole program is written in GNU bc. To run it, use ```bc learnbc.bc```.
|
||||
|
1135
be-by/python-by.html.markdown
Normal file
1135
be-by/python-by.html.markdown
Normal file
File diff suppressed because it is too large
Load Diff
288
bqn.html.markdown
Normal file
288
bqn.html.markdown
Normal file
@ -0,0 +1,288 @@
|
||||
---
|
||||
language: BQN
|
||||
filename: learnbqn.bqn
|
||||
contributors:
|
||||
- ["Raghu Ranganathan", "https://github.com/razetime"]
|
||||
---
|
||||
|
||||
BQN is a modern array language (similar to APL) that aims to eliminate burdensome aspects of the APL tradition.
|
||||
|
||||
It is recommended to try these code examples out in a REPL. The [online REPL](https://mlochbaum.github.io/BQN/try.html) is
|
||||
recommended for quick start, since it comes with keyboard and easy to access help. You can try building
|
||||
[CBQN](https://github.com/dzaima/CBQN) for a local install, but it will need keyboard setup.
|
||||
|
||||
```bqn
|
||||
# This is a comment.
|
||||
# The characters ',' and `⋄` are statement separators.
|
||||
|
||||
##################
|
||||
# Main datatypes #
|
||||
##################
|
||||
|
||||
# Numbers
|
||||
1,2,3,4
|
||||
¯1,¯2,¯3 # Negative numbers are written with a high minus
|
||||
π,∞,¯π,¯∞ # Pi and Infinity are defined constants
|
||||
1_234_456 # You can add underscores in between numbers
|
||||
# This does not change their value
|
||||
1.3E4 # Scientific notation is supported
|
||||
|
||||
# Characters
|
||||
'a','⥊'
|
||||
'
|
||||
' # Yes, you can put *any* character in a character literal
|
||||
@ # Null character ('\0' in C)
|
||||
# Arrays
|
||||
1‿2‿3 # Stranding, good for simple lists
|
||||
⟨1,2,3⟩ # General list notation
|
||||
⟨1‿2,2‿3⟩ # Both can be mixed
|
||||
[1‿2,2‿3] # Array notation
|
||||
# An array is multidimensional, as opposed to containing sublists.
|
||||
# It must be rectangular in shape (a grid structure rather than a tree structure)
|
||||
[1‿2‿3,4‿5] # This is hence invalid
|
||||
# May be familiar coming from Numpy, MATLAB and similar languages.
|
||||
"asdf" # Character array (String)
|
||||
"newline
|
||||
separated" # Allows newlines
|
||||
"quo""tes" # Escape a double quote by typing it twice
|
||||
# Functions
|
||||
1{𝕨+𝕩}3 # All functions are infix
|
||||
# 𝕨 is left argument, 𝕩 is right argument
|
||||
{-𝕩}5 # 𝕨 can be omitted
|
||||
1+3 # Same as the above
|
||||
{𝕊𝕩} # 𝕊 is a recursive call
|
||||
# (this function will loop forever)
|
||||
{𝕨 𝕊 𝕩: 𝕨+𝕩} # Functions can have headers (too many cases to discuss here)
|
||||
# Headers can define arity
|
||||
{𝕊 a‿b: a}1‿2 # and also do basic pattern matching
|
||||
# (returns 1)
|
||||
|
||||
# Modifiers (higher order functions)
|
||||
{𝕗,𝔽,𝕘,𝔾} # 𝔽 and 𝔾 are the operands as callable functions
|
||||
# 𝕗 and 𝕘 are the operands as values
|
||||
{𝔽𝕩} # 1-modifiers use 𝔽/𝕗 ONLY
|
||||
˜,˘,¨,⁼,⌜ # primitive 1-modifiers are superscripts
|
||||
{𝕨𝔽𝔾𝕩} # 2-modifiers MUST use both 𝔽/𝕗 and 𝔾/𝕘 in body or header
|
||||
⊸,∘,○,⟜ # primitive 2-modifiers all have circles
|
||||
+{⟨𝕗⟩} # returns ⟨ + ⟩
|
||||
1-{𝔽 𝕨 𝔾 𝕩 }×2 # returns ¯2 (operators are *also* infix)
|
||||
# (same as 1 -○× 2)
|
||||
|
||||
# Trains (Special form of function composition)
|
||||
(+´÷≠) # Average (but how?)
|
||||
# The above train is an F G H train, where
|
||||
# (F G H) 𝕩 → (F 𝕩) G (H 𝕩)
|
||||
# F ← +´, G ← ÷, H ← ≠
|
||||
# In explicit form, this is
|
||||
{(+´𝕩)÷≠𝕩}
|
||||
# The second pattern is (f g) 𝕩 → f g 𝕩.
|
||||
# longer trains are complex arrangements of these patterns, involving constants and Nothing (·).
|
||||
# Read more about trains at https://mlochbaum.github.io/BQN/doc/train.html
|
||||
|
||||
# Evaluation order:
|
||||
# BQN evaluates functions right to left with no precedence rules governing *functions*. Functions are what
|
||||
# one would call operators in a mainstream language.
|
||||
1÷2+3 # 1÷(2+3) = 0.2
|
||||
(1÷2)+3 # ((1÷2)+3) = 1.5
|
||||
|
||||
# Modifiers:
|
||||
# Modifiers are higher order functions, and bind tighter than functions. Modifiers execute left to right.
|
||||
# Modifiers can take non-function arguments e.g. Constant (`˙`)
|
||||
+
|
||||
1+˜2+○-∘×3 # 1(+˜)(2((+○-)∘×)3)
|
||||
|
||||
# Variables
|
||||
# Since the case of a variable matters to determine what it means, BQN variables are *case insensitive*
|
||||
# The case that a variable is written in can change the way it is interpreted by BQN.
|
||||
# Eg. `F` refers to a value as a callable function, whereas `f` refers to the same variable as just a value.
|
||||
# Variable assignment is done with `←`. Variables have naming conventions based on their value:
|
||||
subject ← 1‿2‿3 # Arrays, single values, namespaces come under this
|
||||
# name must start with with a lowercase letter
|
||||
Function ← {𝕨+𝕩} # Primitive and user defined functions come under this, both monadic and dyadic
|
||||
# Starts with an uppercase letter
|
||||
_1modifier ← {𝕨𝔽𝕩} # Starts with an underscore
|
||||
_2modifier_ ← {𝔽𝕨𝔾𝕩} # Starts and ends with an underscore
|
||||
# Variable modification is done with `↩`. An existing name cannot be reassigned with `←`.
|
||||
Func ↩ {"Hello"∾𝕩}
|
||||
array_or_atom +↩ 2 # You can use a dyadic function for modification
|
||||
#≡ 3‿4‿5
|
||||
array_or_atom -↩ # Or a monadic function.
|
||||
#≡ ¯3‿¯4‿¯5
|
||||
# Due to all functions being infix, you can use your own functions for modification as well:
|
||||
array_or_atom {2⋆𝕩}↩ #≡ ⟨ 0.125, 0.0625, 0.03125 ⟩
|
||||
|
||||
##################
|
||||
# BQN Primitives #
|
||||
##################
|
||||
# All of BQN's base primitives are a single character long. Refer to https://mlochbaum.github.io/BQN/help/index.html for
|
||||
# examples.
|
||||
# Here we will look at a few primitives from each section. You will want to consult the docs for detailed explanations.
|
||||
|
||||
# Primitive Functions
|
||||
# All BQN functions are variadic, and can take one or two arguments. The base functions have both monadic and dyadic overloads.
|
||||
# Usually the two overloads for a function are related.
|
||||
|
||||
## Arithmetic Functions
|
||||
+, -, ×, ÷ # Add, Subtract, Signum/Multiply, Reciprocal/Divide , '*' does NOT do multiplication
|
||||
# ⌊∘÷ does floor division
|
||||
√, ⋆ # Square root/Nth root, e^x/Power
|
||||
# All Arithmetic functions vectorize:
|
||||
1 + 2‿3‿4 #≡ 3‿4‿5
|
||||
1‿2‿3 + 2‿3‿4 #≡ 3‿5‿7
|
||||
# Character arithmetic(+ and - only):
|
||||
"abc"+3 #≡ "def"
|
||||
'a'-'d' #≡ ¯3
|
||||
|
||||
## Logic Functions
|
||||
∧, ∨, ¬ # For Booleans, return 1 or 0
|
||||
≤, <, >, ≥, = # Vectorizing comparisons
|
||||
≡, ≢ # Nonvectorizing comparisons
|
||||
|
||||
## Array manipulation Functions
|
||||
↕ # Make a range
|
||||
∾, ≍, ⋈ # Joining arrays together
|
||||
a←1‿2‿3,b←4‿5 # Let us take a and b.
|
||||
a∾b #≡ 1‿2‿3‿4‿5
|
||||
a≍b # Same as previous, since a and b are not multidimensional
|
||||
# Adds an extra dimension, similar to a ⋈ for multidimensional arrays.
|
||||
a⋈b #≡ ⟨1‿2‿3, 4‿5⟩
|
||||
⊑, ⊏ # Indexing
|
||||
1⊑1‿2‿3 #≡ 2 (BQN is 0-indexed)
|
||||
1‿2⊏1‿2‿3 #≡ 2‿3 (for multiple indices)
|
||||
↑, ↓ # Getting a prefix, suffix of an array.
|
||||
# together they can be used for slicing
|
||||
⥊ # Reshape/repeat items to create a new array
|
||||
|
||||
# Primitive 1-Modifiers
|
||||
## Looping combinators
|
||||
¨, ˘, ⌜ # Mapping/Zipping
|
||||
´, ˝ # Fold from right
|
||||
` # Scan from left
|
||||
|
||||
## General combinators
|
||||
˜ # duplicate argument/swap args - Very useful!
|
||||
˙ # Create constant function
|
||||
1 -˜ 2 #≡ 2 - 1
|
||||
+˜ 2 #≡ 2 + 2
|
||||
|
||||
# Primitive 2-modifiers
|
||||
## Control Flow
|
||||
◶ # Choose from a list of funcs
|
||||
⍟ # Repeat n times
|
||||
|
||||
## General Combinators
|
||||
⊸, ⟜ # hook, hookf
|
||||
∘, ○ # simple function composition
|
||||
|
||||
##########
|
||||
# Blocks #
|
||||
##########
|
||||
# Code delimited by {}
|
||||
# Lexically scoped
|
||||
# For more info: https://mlochbaum.github.io/BQN/doc/block.html
|
||||
# Can have headers, which are ways to explicitly define what a block should be.
|
||||
# A block without headers is automatically inferred from its special variables (𝕨, 𝕩, ...).
|
||||
|
||||
# Function blocks
|
||||
# Implicit variables(Capitals are functions):
|
||||
# - 𝕨, 𝕎 left argument
|
||||
# - 𝕩, 𝕏 right argument
|
||||
# - 𝕤, 𝕊 represent the block itself
|
||||
# Optional: one or more headers that trigger based on
|
||||
# - pattern match (':') o
|
||||
# - condition ('?') (similar to if-then-else)
|
||||
|
||||
{ # A factorial using headers:
|
||||
𝕊 0: 1;
|
||||
𝕊 𝕩: 𝕩×𝕊 𝕩-1
|
||||
}
|
||||
{ # Factorial with predicates
|
||||
𝕩<2 ? 1; # Similar to an if-else pattern.
|
||||
𝕩×𝕊 𝕩-1
|
||||
}
|
||||
|
||||
# Modifier blocks
|
||||
# create 1-modifiers and 2-modifiers, which have separate types
|
||||
# Implicit variables(Capitals are functions):
|
||||
# - has 𝕨 and 𝕩 if needed
|
||||
# - 𝕗, 𝔽 left operand
|
||||
# - 𝕘, 𝔾 right operand (only in 2-modifiers)
|
||||
# - 𝕣 represents the block itself* (requires underscores as per convention)
|
||||
# Same header rules as functions.
|
||||
{ 𝕨=0 ? 𝔽 𝕩; 𝔾 𝕩 } # execute 𝔽 or 𝔾 based on whether left argument is 0.
|
||||
|
||||
# Namespace blocks
|
||||
# Create immutable namespaces with fields
|
||||
# Require exports (`⇐`) for accessible fields.
|
||||
# Use '.' for field access
|
||||
n←{
|
||||
A←+
|
||||
b⇐4
|
||||
}
|
||||
n.b #≡ 4
|
||||
n.a # ERROR
|
||||
|
||||
# Immediate Blocks
|
||||
# No arguments taken
|
||||
# Run the code inside and return the last statement
|
||||
# Often responsible for strange errors.
|
||||
# Can be mistaken for other blocks easily
|
||||
# Good for avoiding scoping issues
|
||||
{
|
||||
1‿2‿3
|
||||
}
|
||||
{+} # Trick for returning a function as a value
|
||||
####################
|
||||
# Basic constructs #
|
||||
####################
|
||||
# Functional programming
|
||||
# `¨` is used for mapping, as discussed before:
|
||||
{𝕩∾2}¨1‿2‿3 #≡ ⟨1‿2,2‿2,3‿2⟩
|
||||
# ⋈¨ is a plain zip, which produces pairs.
|
||||
# `¨` acts as a zipWith when used with two arguments:
|
||||
1‿2‿3 {⟨𝕩+2,2⥊𝕨⟩} 4‿5‿6 #≡ ⟨⟨6,1‿1⟩,⟨7,2‿2⟩,⟨8,3‿3⟩⟩
|
||||
# `/` is replicate, which serves several purposes *including* filtering.
|
||||
# elements in 𝕩 are repeated by the corresponding number in 𝕨.
|
||||
1‿2‿3‿0/4‿5‿6‿7 #≡ 4‿5‿5‿6‿6‿6
|
||||
# a simple filter idiom is F⊸/:
|
||||
{2|𝕩}⊸/67‿42‿83 # keep the odd elements
|
||||
#≡ 67‿83
|
||||
|
||||
# Conditionals
|
||||
# There are two main ways to define a conditional.
|
||||
## Predicate headers
|
||||
{
|
||||
𝕩 > 2: "greater than 2";
|
||||
𝕩 < 2: "lesser than 2";
|
||||
"equal to 2"
|
||||
}
|
||||
|
||||
## Choose (function-based)
|
||||
# - 2-modifier
|
||||
# - 𝔾: list of functions that serve as bodies
|
||||
# - 𝔽: condition function that specifies which function from 𝔾 to select
|
||||
# The same conditional as above would be:
|
||||
{⊑/⟨𝕩>2, 𝕩<2, 𝕩=2⟩}◶⟨
|
||||
{𝕊: "greater than 2"}
|
||||
{𝕊: "lesser than 2"}
|
||||
{𝕊: "equal to 2"}
|
||||
⟩
|
||||
|
||||
## Some helpers for conditionals
|
||||
If ← {𝕏⍟𝕎@}´ # Used as If ⟨Condition, Block⟩
|
||||
IfElse ← {c‿T‿F: c◶F‿T@} # Used as IfElse ⟨Condition, Block, ElseBlock⟩
|
||||
|
||||
# Looping
|
||||
# The primary form of unbounded looping is recursion (performed with 𝕊).
|
||||
# BQN does not eliminate tail calls, but the while idiom can be used to work around this:
|
||||
While ← {𝕩{𝔽⍟𝔾∘𝔽_𝕣_𝔾∘𝔽⍟𝔾𝕩}𝕨@}´ # While 1‿{... to run forever
|
||||
DoWhile ← {𝕏@ ⋄ While 𝕨‿𝕩}´
|
||||
# A For loop can be done with ¨, functions need not be pure.
|
||||
```
|
||||
|
||||
## Ready for more?
|
||||
|
||||
- [Quickstart guide](https://mlochbaum.github.io/BQN/doc/quick.html)
|
||||
- [Full length, explained documentation](https://mlochbaum.github.io/BQN/doc/index.html)
|
||||
- [Short docs](https://mlochbaum.github.io/BQN/help/index.html)
|
||||
- [BQN community!](https://mlochbaum.github.io/BQN/community/index.html)
|
@ -31,7 +31,7 @@ one of the most widely-used programming languages.
|
||||
// Comparison to C
|
||||
//////////////////
|
||||
|
||||
// C++ is _almost_ a superset of C and shares its basic syntax for
|
||||
// C++ is almost a superset of C and shares its basic syntax for
|
||||
// variable declarations, primitive types, and functions.
|
||||
|
||||
// Just like in C, your program's entry point is a function called
|
||||
@ -55,24 +55,26 @@ int main(int argc, char** argv)
|
||||
|
||||
// However, C++ varies in some of the following ways:
|
||||
|
||||
// In C++, character literals are chars
|
||||
sizeof('c') == sizeof(char) == 1
|
||||
// In C++, character literals are chars, therefore the size is 1
|
||||
sizeof('c') == sizeof(char)
|
||||
|
||||
// In C, character literals are ints
|
||||
// In C, character literals are ints, therefore the size is 4
|
||||
sizeof('c') == sizeof(int)
|
||||
|
||||
|
||||
// C++ has strict prototyping
|
||||
void func(); // function which accepts no arguments
|
||||
void func(void); // same as earlier
|
||||
|
||||
// In C
|
||||
void func(); // function which may accept any number of arguments
|
||||
void func(); // function which may accept any number of arguments with unknown type
|
||||
void func(void); // function which accepts no arguments
|
||||
|
||||
// Use nullptr instead of NULL in C++
|
||||
int* ip = nullptr;
|
||||
|
||||
// C standard headers are available in C++.
|
||||
// C headers end in .h, while
|
||||
// Most C standard headers are available in C++.
|
||||
// C headers generally end with .h, while
|
||||
// C++ headers are prefixed with "c" and have no ".h" suffix.
|
||||
|
||||
// The C++ standard version:
|
||||
@ -101,7 +103,7 @@ void print(char const* myString)
|
||||
|
||||
void print(int myInt)
|
||||
{
|
||||
printf("My int is %d", myInt);
|
||||
printf("My int is %d\n", myInt);
|
||||
}
|
||||
|
||||
int main()
|
||||
@ -160,7 +162,7 @@ namespace Second {
|
||||
}
|
||||
void bar()
|
||||
{
|
||||
printf("This is Second::bar\n");
|
||||
printf("This is Second::bar\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -193,22 +195,24 @@ int main()
|
||||
|
||||
#include <iostream> // Include for I/O streams
|
||||
|
||||
using namespace std; // Streams are in the std namespace (standard library)
|
||||
|
||||
int main()
|
||||
{
|
||||
int myInt;
|
||||
int myInt;
|
||||
|
||||
// Prints to stdout (or terminal/screen)
|
||||
cout << "Enter your favorite number:\n";
|
||||
// Takes in input
|
||||
cin >> myInt;
|
||||
// Prints to stdout (or terminal/screen)
|
||||
// std::cout referring the access to the std namespace
|
||||
std::cout << "Enter your favorite number:\n";
|
||||
// Takes in input
|
||||
std::cin >> myInt;
|
||||
|
||||
// cout can also be formatted
|
||||
cout << "Your favorite number is " << myInt << '\n';
|
||||
// prints "Your favorite number is <myInt>"
|
||||
// cout can also be formatted
|
||||
std::cout << "Your favorite number is " << myInt << '\n';
|
||||
// prints "Your favorite number is <myInt>"
|
||||
|
||||
cerr << "Used for error messages";
|
||||
std::cerr << "Used for error messages";
|
||||
|
||||
// flush string stream buffer with new line
|
||||
std::cout << "I flushed it away" << std::endl;
|
||||
}
|
||||
|
||||
//////////
|
||||
@ -218,20 +222,27 @@ int main()
|
||||
// Strings in C++ are objects and have many member functions
|
||||
#include <string>
|
||||
|
||||
using namespace std; // Strings are also in the namespace std (standard library)
|
||||
|
||||
string myString = "Hello";
|
||||
string myOtherString = " World";
|
||||
std::string myString = "Hello";
|
||||
std::string myOtherString = " World";
|
||||
|
||||
// + is used for concatenation.
|
||||
cout << myString + myOtherString; // "Hello World"
|
||||
std::cout << myString + myOtherString; // "Hello World"
|
||||
|
||||
cout << myString + " You"; // "Hello You"
|
||||
std::cout << myString + " You"; // "Hello You"
|
||||
|
||||
// C++ string length can be found from either string::length() or string::size()
|
||||
cout << myString.length() + myOtherString.size(); // Outputs 11 (= 5 + 6).
|
||||
|
||||
// C++ strings are mutable.
|
||||
myString.append(" Dog");
|
||||
cout << myString; // "Hello Dog"
|
||||
std::cout << myString; // "Hello Dog"
|
||||
|
||||
// C++ can handle C-style strings with related functions using cstrings
|
||||
#include <cstring>
|
||||
|
||||
char myOldString[10] = "Hello CPP";
|
||||
cout << myOldString;
|
||||
cout << "Length = " << strlen(myOldString); // Length = 9
|
||||
|
||||
/////////////
|
||||
// References
|
||||
@ -245,35 +256,32 @@ cout << myString; // "Hello Dog"
|
||||
// No * is needed for dereferencing and
|
||||
// & (address of) is not used for assignment.
|
||||
|
||||
using namespace std;
|
||||
std::string foo = "I am foo";
|
||||
std::string bar = "I am bar";
|
||||
|
||||
string foo = "I am foo";
|
||||
string bar = "I am bar";
|
||||
|
||||
|
||||
string& fooRef = foo; // This creates a reference to foo.
|
||||
std::string& fooRef = foo; // This creates a reference to foo.
|
||||
fooRef += ". Hi!"; // Modifies foo through the reference
|
||||
cout << fooRef; // Prints "I am foo. Hi!"
|
||||
std::cout << fooRef; // Prints "I am foo. Hi!"
|
||||
|
||||
std::cout << &fooRef << '\n'; // Prints the address of foo
|
||||
// Doesn't reassign "fooRef". This is the same as "foo = bar", and
|
||||
// foo == "I am bar"
|
||||
// after this line.
|
||||
cout << &fooRef << endl; //Prints the address of foo
|
||||
fooRef = bar;
|
||||
cout << &fooRef << endl; //Still prints the address of foo
|
||||
cout << fooRef; // Prints "I am bar"
|
||||
std::cout << &fooRef << '\n'; // Still prints the address of foo
|
||||
std::cout << fooRef << '\n'; // Prints "I am bar"
|
||||
|
||||
// The address of fooRef remains the same, i.e. it is still referring to foo.
|
||||
|
||||
|
||||
const string& barRef = bar; // Create a const reference to bar.
|
||||
const std::string& barRef = bar; // Create a const reference to bar.
|
||||
// Like C, const values (and pointers and references) cannot be modified.
|
||||
barRef += ". Hi!"; // Error, const references cannot be modified.
|
||||
|
||||
// Sidetrack: Before we talk more about references, we must introduce a concept
|
||||
// called a temporary object. Suppose we have the following code:
|
||||
string tempObjectFun() { ... }
|
||||
string retVal = tempObjectFun();
|
||||
std::string tempObjectFun() { ... }
|
||||
std::string retVal = tempObjectFun();
|
||||
|
||||
// What happens in the second line is actually:
|
||||
// - a string object is returned from tempObjectFun
|
||||
@ -296,27 +304,27 @@ foo(bar(tempObjectFun()))
|
||||
// which case its life gets extended to the current scope:
|
||||
|
||||
void constReferenceTempObjectFun() {
|
||||
// constRef gets the temporary object, and it is valid until the end of this
|
||||
// function.
|
||||
const string& constRef = tempObjectFun();
|
||||
...
|
||||
// constRef gets the temporary object, and it is valid until the end of this
|
||||
// function.
|
||||
const std::string& constRef = tempObjectFun();
|
||||
...
|
||||
}
|
||||
|
||||
// Another kind of reference introduced in C++11 is specifically for temporary
|
||||
// objects. You cannot have a variable of its type, but it takes precedence in
|
||||
// overload resolution:
|
||||
|
||||
void someFun(string& s) { ... } // Regular reference
|
||||
void someFun(string&& s) { ... } // Reference to temporary object
|
||||
void someFun(std::string& s) { ... } // Regular reference
|
||||
void someFun(std::string&& s) { ... } // Reference to temporary object
|
||||
|
||||
string foo;
|
||||
std::string foo;
|
||||
someFun(foo); // Calls the version with regular reference
|
||||
someFun(tempObjectFun()); // Calls the version with temporary reference
|
||||
|
||||
// For example, you will see these two versions of constructors for
|
||||
// std::basic_string:
|
||||
basic_string(const basic_string& other);
|
||||
basic_string(basic_string&& other);
|
||||
std::basic_string(const basic_string& other);
|
||||
std::basic_string(basic_string&& other);
|
||||
|
||||
// Idea being if we are constructing a new string from a temporary object (which
|
||||
// is going to be destroyed soon anyway), we can have a more efficient
|
||||
@ -331,15 +339,15 @@ basic_string(basic_string&& other);
|
||||
// easier visualization and reading of code
|
||||
enum ECarTypes
|
||||
{
|
||||
Sedan,
|
||||
Hatchback,
|
||||
SUV,
|
||||
Wagon
|
||||
Sedan,
|
||||
Hatchback,
|
||||
SUV,
|
||||
Wagon
|
||||
};
|
||||
|
||||
ECarTypes GetPreferredCarType()
|
||||
{
|
||||
return ECarTypes::Hatchback;
|
||||
return ECarTypes::Hatchback;
|
||||
}
|
||||
|
||||
// As of C++11 there is an easy way to assign a type to the enum which can be
|
||||
@ -347,21 +355,21 @@ ECarTypes GetPreferredCarType()
|
||||
// the desired type and their respective constants
|
||||
enum ECarTypes : uint8_t
|
||||
{
|
||||
Sedan, // 0
|
||||
Hatchback, // 1
|
||||
SUV = 254, // 254
|
||||
Hybrid // 255
|
||||
Sedan, // 0
|
||||
Hatchback, // 1
|
||||
SUV = 254, // 254
|
||||
Hybrid // 255
|
||||
};
|
||||
|
||||
void WriteByteToFile(uint8_t InputValue)
|
||||
{
|
||||
// Serialize the InputValue to a file
|
||||
// Serialize the InputValue to a file
|
||||
}
|
||||
|
||||
void WritePreferredCarTypeToFile(ECarTypes InputCarType)
|
||||
{
|
||||
// The enum is implicitly converted to a uint8_t due to its declared enum type
|
||||
WriteByteToFile(InputCarType);
|
||||
// The enum is implicitly converted to a uint8_t due to its declared enum type
|
||||
WriteByteToFile(InputCarType);
|
||||
}
|
||||
|
||||
// On the other hand you may not want enums to be accidentally cast to an integer
|
||||
@ -369,22 +377,22 @@ void WritePreferredCarTypeToFile(ECarTypes InputCarType)
|
||||
// won't be implicitly converted
|
||||
enum class ECarTypes : uint8_t
|
||||
{
|
||||
Sedan, // 0
|
||||
Hatchback, // 1
|
||||
SUV = 254, // 254
|
||||
Hybrid // 255
|
||||
Sedan, // 0
|
||||
Hatchback, // 1
|
||||
SUV = 254, // 254
|
||||
Hybrid // 255
|
||||
};
|
||||
|
||||
void WriteByteToFile(uint8_t InputValue)
|
||||
{
|
||||
// Serialize the InputValue to a file
|
||||
// Serialize the InputValue to a file
|
||||
}
|
||||
|
||||
void WritePreferredCarTypeToFile(ECarTypes InputCarType)
|
||||
{
|
||||
// Won't compile even though ECarTypes is a uint8_t due to the enum
|
||||
// being declared as an "enum class"!
|
||||
WriteByteToFile(InputCarType);
|
||||
// Won't compile even though ECarTypes is a uint8_t due to the enum
|
||||
// being declared as an "enum class"!
|
||||
WriteByteToFile(InputCarType);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////
|
||||
@ -565,7 +573,7 @@ Point& Point::operator+=(const Point& rhs)
|
||||
{
|
||||
x += rhs.x;
|
||||
y += rhs.y;
|
||||
|
||||
|
||||
// `this` is a pointer to the object, on which a method is called.
|
||||
return *this;
|
||||
}
|
||||
@ -577,7 +585,7 @@ int main () {
|
||||
// Point up calls the + (function) with right as its parameter
|
||||
Point result = up + right;
|
||||
// Prints "Result is upright (1,1)"
|
||||
cout << "Result is upright (" << result.x << ',' << result.y << ")\n";
|
||||
std::cout << "Result is upright (" << result.x << ',' << result.y << ")\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -645,7 +653,7 @@ barkThreeTimes(fluffy); // Prints "Fluffy barks" three times.
|
||||
// Template parameters don't have to be classes:
|
||||
template<int Y>
|
||||
void printMessage() {
|
||||
cout << "Learn C++ in " << Y << " minutes!" << endl;
|
||||
std::cout << "Learn C++ in " << Y << " minutes!\n";
|
||||
}
|
||||
|
||||
// And you can explicitly specialize templates for more efficient code. Of
|
||||
@ -654,7 +662,7 @@ void printMessage() {
|
||||
// even if you explicitly specified all parameters.
|
||||
template<>
|
||||
void printMessage<10>() {
|
||||
cout << "Learn C++ faster in only 10 minutes!" << endl;
|
||||
std::cout << "Learn C++ faster in only 10 minutes!\n";
|
||||
}
|
||||
|
||||
printMessage<20>(); // Prints "Learn C++ in 20 minutes!"
|
||||
@ -707,6 +715,9 @@ void doSomethingWithAFile(const char* filename)
|
||||
// To begin with, assume nothing can fail.
|
||||
|
||||
FILE* fh = fopen(filename, "r"); // Open the file in read mode.
|
||||
if (fh == NULL) {
|
||||
// Handle possible error
|
||||
}
|
||||
|
||||
doSomethingWithTheFile(fh);
|
||||
doSomethingElseWithIt(fh);
|
||||
@ -826,10 +837,10 @@ void doSomethingWithAFile(const std::string& filename)
|
||||
|
||||
// Generally a smart pointer is a class which wraps a "raw pointer" (usage of "new"
|
||||
// respectively malloc/calloc in C). The goal is to be able to
|
||||
// manage the lifetime of the object being pointed to without ever needing to explicitly delete
|
||||
// manage the lifetime of the object being pointed to without ever needing to explicitly delete
|
||||
// the object. The term itself simply describes a set of pointers with the
|
||||
// mentioned abstraction.
|
||||
// Smart pointers should preferred over raw pointers, to prevent
|
||||
// Smart pointers should be preferred over raw pointers, to prevent
|
||||
// risky memory leaks, which happen if you forget to delete an object.
|
||||
|
||||
// Usage of a raw pointer:
|
||||
@ -846,9 +857,9 @@ delete ptr;
|
||||
// Usage of "std::shared_ptr":
|
||||
void foo()
|
||||
{
|
||||
// It's no longer necessary to delete the Dog.
|
||||
std::shared_ptr<Dog> doggo(new Dog());
|
||||
doggo->bark();
|
||||
// It's no longer necessary to delete the Dog.
|
||||
std::shared_ptr<Dog> doggo(new Dog());
|
||||
doggo->bark();
|
||||
}
|
||||
|
||||
// Beware of possible circular references!!!
|
||||
@ -858,7 +869,7 @@ std::shared_ptr<Dog> doggo_two(new Dog());
|
||||
doggo_one = doggo_two; // p1 references p2
|
||||
doggo_two = doggo_one; // p2 references p1
|
||||
|
||||
// There are several kinds of smart pointers.
|
||||
// There are several kinds of smart pointers.
|
||||
// The way you have to use them is always the same.
|
||||
// This leads us to the question: when should we use each kind of smart pointer?
|
||||
// std::unique_ptr - use it when you just want to hold one reference to
|
||||
@ -884,22 +895,23 @@ doggo_two = doggo_one; // p2 references p1
|
||||
// Vector (Dynamic array)
|
||||
// Allow us to Define the Array or list of objects at run time
|
||||
#include <vector>
|
||||
string val;
|
||||
vector<string> my_vector; // initialize the vector
|
||||
cin >> val;
|
||||
std::string val;
|
||||
std::vector<string> my_vector; // initialize the vector
|
||||
std::cin >> val;
|
||||
|
||||
my_vector.push_back(val); // will push the value of 'val' into vector ("array") my_vector
|
||||
my_vector.push_back(val); // will push the value into the vector again (now having two elements)
|
||||
|
||||
// To iterate through a vector we have 2 choices:
|
||||
// Either classic looping (iterating through the vector from index 0 to its last index):
|
||||
for (int i = 0; i < my_vector.size(); i++) {
|
||||
cout << my_vector[i] << endl; // for accessing a vector's element we can use the operator []
|
||||
std::cout << my_vector[i] << '\n'; // for accessing a vector's element we can use the operator []
|
||||
}
|
||||
|
||||
// or using an iterator:
|
||||
vector<string>::iterator it; // initialize the iterator for vector
|
||||
for (it = my_vector.begin(); it != my_vector.end(); ++it) {
|
||||
cout << *it << endl;
|
||||
std::cout << *it << '\n';
|
||||
}
|
||||
|
||||
// Set
|
||||
@ -908,7 +920,7 @@ for (it = my_vector.begin(); it != my_vector.end(); ++it) {
|
||||
// without any other functions or code.
|
||||
|
||||
#include<set>
|
||||
set<int> ST; // Will initialize the set of int data type
|
||||
std::set<int> ST; // Will initialize the set of int data type
|
||||
ST.insert(30); // Will insert the value 30 in set ST
|
||||
ST.insert(10); // Will insert the value 10 in set ST
|
||||
ST.insert(20); // Will insert the value 20 in set ST
|
||||
@ -920,9 +932,9 @@ ST.insert(30); // Will insert the value 30 in set ST
|
||||
ST.erase(20); // Will erase element with value 20
|
||||
// Set ST: 10 30
|
||||
// To iterate through Set we use iterators
|
||||
set<int>::iterator it;
|
||||
for(it=ST.begin();it!=ST.end();it++) {
|
||||
cout << *it << endl;
|
||||
std::set<int>::iterator it;
|
||||
for (it = ST.begin(); it != ST.end(); it++) {
|
||||
std::cout << *it << '\n';
|
||||
}
|
||||
// Output:
|
||||
// 10
|
||||
@ -930,7 +942,7 @@ for(it=ST.begin();it!=ST.end();it++) {
|
||||
|
||||
// To clear the complete container we use Container_name.clear()
|
||||
ST.clear();
|
||||
cout << ST.size(); // will print the size of set ST
|
||||
std::cout << ST.size(); // will print the size of set ST
|
||||
// Output: 0
|
||||
|
||||
// NOTE: for duplicate elements we can use multiset
|
||||
@ -942,7 +954,7 @@ cout << ST.size(); // will print the size of set ST
|
||||
// and a mapped value, following a specific order.
|
||||
|
||||
#include<map>
|
||||
map<char, int> mymap; // Will initialize the map with key as char and value as int
|
||||
std::map<char, int> mymap; // Will initialize the map with key as char and value as int
|
||||
|
||||
mymap.insert(pair<char,int>('A',1));
|
||||
// Will insert value 1 for key A
|
||||
@ -950,16 +962,16 @@ mymap.insert(pair<char,int>('Z',26));
|
||||
// Will insert value 26 for key Z
|
||||
|
||||
// To iterate
|
||||
map<char,int>::iterator it;
|
||||
for (it=mymap.begin(); it!=mymap.end(); ++it)
|
||||
std::cout << it->first << "->" << it->second << std::endl;
|
||||
std::map<char,int>::iterator it;
|
||||
for (it = mymap.begin(); it != mymap.end(); ++it)
|
||||
std::cout << it->first << "->" << it->second << '\n';
|
||||
// Output:
|
||||
// A->1
|
||||
// Z->26
|
||||
|
||||
// To find the value corresponding to a key
|
||||
it = mymap.find('Z');
|
||||
cout << it->second;
|
||||
std::cout << it->second;
|
||||
|
||||
// Output: 26
|
||||
|
||||
@ -997,7 +1009,7 @@ fooMap.find(Foo(1)); //true
|
||||
// For example, consider sorting a vector of pairs using the second
|
||||
// value of the pair
|
||||
|
||||
vector<pair<int, int> > tester;
|
||||
std::vector<pair<int, int> > tester;
|
||||
tester.push_back(make_pair(3, 6));
|
||||
tester.push_back(make_pair(1, 9));
|
||||
tester.push_back(make_pair(5, 0));
|
||||
@ -1005,7 +1017,7 @@ tester.push_back(make_pair(5, 0));
|
||||
// Pass a lambda expression as third argument to the sort function
|
||||
// sort is from the <algorithm> header
|
||||
|
||||
sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs) {
|
||||
std::sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int, int>& rhs) {
|
||||
return lhs.second < rhs.second;
|
||||
});
|
||||
|
||||
@ -1019,10 +1031,10 @@ sort(tester.begin(), tester.end(), [](const pair<int, int>& lhs, const pair<int,
|
||||
// 4. same as 3, but by value [=]
|
||||
// Example:
|
||||
|
||||
vector<int> dog_ids;
|
||||
std::vector<int> dog_ids;
|
||||
// number_of_dogs = 3;
|
||||
for(int i = 0; i < 3; i++) {
|
||||
dog_ids.push_back(i);
|
||||
for (int i = 0; i < 3; i++) {
|
||||
dog_ids.push_back(i);
|
||||
}
|
||||
|
||||
int weight[3] = {30, 50, 10};
|
||||
@ -1045,15 +1057,15 @@ sort(dog_ids.begin(), dog_ids.end(), [&weight](const int &lhs, const int &rhs) {
|
||||
// You can use a range for loop to iterate over a container
|
||||
int arr[] = {1, 10, 3};
|
||||
|
||||
for(int elem: arr){
|
||||
cout << elem << endl;
|
||||
for (int elem: arr) {
|
||||
cout << elem << endl;
|
||||
}
|
||||
|
||||
// You can use "auto" and not worry about the type of the elements of the container
|
||||
// For example:
|
||||
|
||||
for(auto elem: arr) {
|
||||
// Do something with each element of arr
|
||||
for (auto elem: arr) {
|
||||
// Do something with each element of arr
|
||||
}
|
||||
|
||||
/////////////////////
|
||||
@ -1066,10 +1078,10 @@ for(auto elem: arr) {
|
||||
|
||||
// You can override private methods!
|
||||
class Foo {
|
||||
virtual void bar();
|
||||
virtual void bar();
|
||||
};
|
||||
class FooSub : public Foo {
|
||||
virtual void bar(); // Overrides Foo::bar!
|
||||
virtual void bar(); // Overrides Foo::bar!
|
||||
};
|
||||
|
||||
|
||||
@ -1124,33 +1136,33 @@ const int maxL = 15;
|
||||
auto second = make_tuple(maxN, maxL);
|
||||
|
||||
// Printing elements of 'first' tuple
|
||||
cout << get<0>(first) << " " << get<1>(first) << '\n'; //prints : 10 A
|
||||
std::cout << get<0>(first) << " " << get<1>(first) << '\n'; //prints : 10 A
|
||||
|
||||
// Printing elements of 'second' tuple
|
||||
cout << get<0>(second) << " " << get<1>(second) << '\n'; // prints: 1000000000 15
|
||||
std::cout << get<0>(second) << " " << get<1>(second) << '\n'; // prints: 1000000000 15
|
||||
|
||||
// Unpacking tuple into variables
|
||||
|
||||
int first_int;
|
||||
char first_char;
|
||||
tie(first_int, first_char) = first;
|
||||
cout << first_int << " " << first_char << '\n'; // prints : 10 A
|
||||
std::cout << first_int << " " << first_char << '\n'; // prints : 10 A
|
||||
|
||||
// We can also create tuple like this.
|
||||
|
||||
tuple<int, char, double> third(11, 'A', 3.14141);
|
||||
// tuple_size returns number of elements in a tuple (as a constexpr)
|
||||
|
||||
cout << tuple_size<decltype(third)>::value << '\n'; // prints: 3
|
||||
std::cout << tuple_size<decltype(third)>::value << '\n'; // prints: 3
|
||||
|
||||
// tuple_cat concatenates the elements of all the tuples in the same order.
|
||||
|
||||
auto concatenated_tuple = tuple_cat(first, second, third);
|
||||
// concatenated_tuple becomes = (10, 'A', 1e9, 15, 11, 'A', 3.14141)
|
||||
|
||||
cout << get<0>(concatenated_tuple) << '\n'; // prints: 10
|
||||
cout << get<3>(concatenated_tuple) << '\n'; // prints: 15
|
||||
cout << get<5>(concatenated_tuple) << '\n'; // prints: 'A'
|
||||
std::cout << get<0>(concatenated_tuple) << '\n'; // prints: 10
|
||||
std::cout << get<3>(concatenated_tuple) << '\n'; // prints: 15
|
||||
std::cout << get<5>(concatenated_tuple) << '\n'; // prints: 'A'
|
||||
|
||||
|
||||
///////////////////////////////////
|
||||
@ -1196,12 +1208,11 @@ compl 4 // Performs a bitwise not
|
||||
4 bitor 3 // Performs bitwise or
|
||||
4 bitand 3 // Performs bitwise and
|
||||
4 xor 3 // Performs bitwise xor
|
||||
|
||||
|
||||
```
|
||||
Further Reading:
|
||||
|
||||
* An up-to-date language reference can be found at [CPP Reference](http://cppreference.com/w/cpp).
|
||||
* A tutorial for beginners or experts, covering many modern features and good practices: [LearnCpp.com](https://www.learncpp.com/)
|
||||
* A tutorial covering basics of language and setting up coding environment is available at [TheChernoProject - C++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb).
|
||||
* Additional resources may be found at [CPlusPlus](http://cplusplus.com).
|
||||
## Further Reading:
|
||||
|
||||
- An up-to-date language reference can be found at [CPP Reference](http://cppreference.com/w/cpp).
|
||||
- A tutorial for beginners or experts, covering many modern features and good practices: [LearnCpp.com](https://www.learncpp.com/)
|
||||
- A tutorial covering basics of language and setting up coding environment is available at [TheChernoProject - C++](https://www.youtube.com/playlist?list=PLlrATfBNZ98dudnM48yfGUldqGD0S4FFb).
|
||||
- Additional resources may be found at [CPlusPlus](http://cplusplus.com).
|
||||
|
@ -905,13 +905,11 @@ Node createLinkedList(int *vals, int len);
|
||||
/* a header file but instead put into separate headers or a C file. */
|
||||
|
||||
#endif /* End of the if precompiler directive. */
|
||||
|
||||
```
|
||||
|
||||
## Further Reading
|
||||
|
||||
Best to find yourself a copy of [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language)
|
||||
It is _the_ book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. Be careful, though - it's ancient and it contains some
|
||||
Best to find yourself a copy of [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language). It is _the_ book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. Be careful, though - it's ancient and it contains some
|
||||
inaccuracies (well, ideas that are not considered good anymore) or now-changed practices.
|
||||
|
||||
Another good resource is [Learn C The Hard Way](http://learncodethehardway.org/c/) (not free).
|
||||
@ -922,6 +920,4 @@ It's very important to use proper spacing, indentation and to be consistent with
|
||||
Readable code is better than clever code and fast code. For a good, sane coding style to adopt, see the
|
||||
[Linux kernel coding style](https://www.kernel.org/doc/Documentation/process/coding-style.rst).
|
||||
|
||||
Other than that, Google is your friend.
|
||||
|
||||
[1] [Why isn't sizeof for a struct equal to the sum of sizeof of each member?](https://stackoverflow.com/questions/119123/why-isnt-sizeof-for-a-struct-equal-to-the-sum-of-sizeof-of-each-member)
|
||||
|
@ -95,7 +95,7 @@ salts de línia.` // El mateix tipus
|
||||
// literals Non-ASCII literal. El tipus de Go és UTF-8.
|
||||
g := 'Σ' // El tipus rune, és un àlies de int32 conté un caràcter unicode.
|
||||
|
||||
f := 3.14195 // float64, un número de 64 bits amb coma flotant IEEE-754.
|
||||
f := 3.14159 // float64, un número de 64 bits amb coma flotant IEEE-754.
|
||||
c := 3 + 4i // complex128, representat internament amb dos float64.
|
||||
|
||||
// Sintaxi amb var i inicialitzadors.
|
||||
@ -432,26 +432,26 @@ func requestServer() {
|
||||
|
||||
## Més informació
|
||||
|
||||
L'arrel de tot en Go és la web oficial [official Go web site]
|
||||
(http://golang.org/). Allà es pot seguir el tutorial, jugar interactivament
|
||||
L'arrel de tot en Go és la web oficial [official Go web site](https://go.dev/).
|
||||
Allà es pot seguir el tutorial, jugar interactivament
|
||||
i llegir molt més del que hem vist aquí.En el "tour",
|
||||
[the docs](https://golang.org/doc/) conté informació sobre com escriure codi
|
||||
[the docs](https://go.dev/doc/) conté informació sobre com escriure codi
|
||||
net i efectiu en Go, comandes per empaquetar i generar documentació, i
|
||||
història de les versions.
|
||||
|
||||
És altament recomanable llegir La definició del llenguatge. És fàcil de llegir
|
||||
i sorprenentment curta (com la definició del llenguatge en aquests dies).
|
||||
|
||||
Es pot jugar amb codi a [Go playground](https://play.golang.org/p/tnWMjr16Mm).
|
||||
Es pot jugar amb codi a [Go playground](https://go.dev/play/p/tnWMjr16Mm).
|
||||
Prova de fer canvis en el codi i executar-lo des del navegador! Es pot fer
|
||||
servir [https://play.golang.org](https://play.golang.org) com a [REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) per provar coses i codi
|
||||
servir [https://go.dev/play/](https://go.dev/play/) com a [REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop) per provar coses i codi
|
||||
en el navegador sense haver d'instal·lar Go.
|
||||
|
||||
En la llista de lectures pels estudiants de Go hi ha
|
||||
[el codi font de la llibreria estàndard](http://golang.org/src/pkg/).
|
||||
[el codi font de la llibreria estàndard](https://go.dev/src/).
|
||||
Ampliament comentada, que demostra el fàcil que és de llegir i entendre els
|
||||
programes en Go, l'estil de programació, i les formes de treballar-hi. O es
|
||||
pot clicar en un nom de funció en [la documentació](http://golang.org/pkg/)
|
||||
pot clicar en un nom de funció en [la documentació](https://go.dev/pkg/)
|
||||
i veure'n el codi!
|
||||
|
||||
Un altre gran recurs per aprendre Go és
|
||||
@ -460,5 +460,5 @@ Un altre gran recurs per aprendre Go és
|
||||
Go Mobile afegeix suport per plataformes mòbils (Android i iOS). Es poden
|
||||
escriure aplicacions mòbils o escriure llibreries de paquets de Go, que es
|
||||
poden cridar des de Java (android) i Objective-C (iOS).
|
||||
Comproveu la [Go Mobile page](https://github.com/golang/go/wiki/Mobile) per
|
||||
Comproveu la [Go Mobile page](https://go.dev/wiki/Mobile) per
|
||||
més informació.
|
||||
|
@ -10,10 +10,9 @@ translations:
|
||||
- ["Xavier Sala Pujolar", "http://github.com/utrescu"]
|
||||
---
|
||||
|
||||
Groovy - Un llenguatge dinàmic per la plataforma Java [Llegir-ne més.](http://www.groovy-lang.org/)
|
||||
Groovy - Un llenguatge dinàmic per la plataforma Java [Llegir-ne més](http://www.groovy-lang.org/).
|
||||
|
||||
```groovy
|
||||
|
||||
/*
|
||||
Posa'l en marxa tu mateix:
|
||||
|
||||
@ -286,7 +285,7 @@ def clos = { print it }
|
||||
clos( "hi" )
|
||||
|
||||
/*
|
||||
Groovy pot recordar els resultats dels Closures [1][2][3]
|
||||
Groovy pot recordar els resultats dels Closures
|
||||
*/
|
||||
def cl = {a, b ->
|
||||
sleep(3000) // simula un procés llarg
|
||||
@ -413,8 +412,6 @@ int sum(int x, int y) {
|
||||
}
|
||||
|
||||
assert sum(2,5) == 7
|
||||
|
||||
|
||||
```
|
||||
|
||||
## Per aprendre'n més
|
||||
@ -423,17 +420,10 @@ assert sum(2,5) == 7
|
||||
|
||||
[Cònsola de Groovy](http://groovyconsole.appspot.com/)
|
||||
|
||||
Uneix-te a un [grup d'usuaris Groovy]
|
||||
(http://www.groovy-lang.org/usergroups.html)
|
||||
Uneix-te a un [grup d'usuaris Groovy](http://www.groovy-lang.org/usergroups.html)
|
||||
|
||||
## Llibres
|
||||
|
||||
* [Groovy Goodness] (https://leanpub.com/groovy-goodness-notebook)
|
||||
|
||||
* [Groovy in Action] (http://manning.com/koenig2/)
|
||||
|
||||
* [Programming Groovy 2: Dynamic Productivity for the Java Developer] (http://shop.oreilly.com/product/9781937785307.do)
|
||||
|
||||
[1] http://roshandawrani.wordpress.com/2010/10/18/groovy-new-feature-closures-can-now-memorize-their-results/
|
||||
[2] http://www.solutionsiq.com/resources/agileiq-blog/bid/72880/Programming-with-Groovy-Trampoline-and-Memoize
|
||||
[3] http://mrhaki.blogspot.mx/2011/05/groovy-goodness-cache-closure-results.html
|
||||
* [Groovy Goodness](https://leanpub.com/groovy-goodness-notebook)
|
||||
* [Groovy in Action](http://manning.com/koenig2/)
|
||||
* [Programming Groovy 2: Dynamic Productivity for the Java Developer](http://shop.oreilly.com/product/9781937785307.do)
|
||||
|
@ -160,7 +160,6 @@ article tracta principalment la sintaxi de l'HTML i alguns consells útils.
|
||||
<td>Segona fila, segona columna</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
```
|
||||
|
||||
## Ús
|
||||
|
@ -379,7 +379,6 @@ fun useObject() {
|
||||
ObjectExample.hello()
|
||||
val someRef: Any = ObjectExample // podem fer servir el nom de l'objecte
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
### Per llegir més
|
||||
|
@ -1,864 +0,0 @@
|
||||
---
|
||||
language: Cairo
|
||||
filename: learnCairo.sol
|
||||
contributors:
|
||||
- ["Darlington Nnam", "https://github.com/Darlington02"]
|
||||
---
|
||||
|
||||
# Cairo
|
||||
|
||||
Cairo is a Turing-complete language that allows you write provable programs
|
||||
(where one party can prove to another that a certain computation was executed
|
||||
correctly) on StarkNet.
|
||||
|
||||
## StarkNet
|
||||
|
||||
StarkNet is a decentralized ZK-rollup that operates as an Ethereum layer 2
|
||||
chain.
|
||||
|
||||
In this document, we are going to be going in-depth into understanding Cairo's
|
||||
syntax and how you could create and deploy a Cairo smart contract on StarkNet.
|
||||
|
||||
**NB: As at the time of this writing, StarkNet is still at v0.10.3, with Cairo
|
||||
1.0 coming soon. The ecosystem is young and evolving very fast, so you might
|
||||
want to check the [official docs](https://www.cairo-lang.org/docs) to confirm
|
||||
this document is still up-to-date. Pull requests are welcome!**
|
||||
|
||||
## Setting Up A Development Environment
|
||||
|
||||
Before we get started writing codes, we will need to setup a Cairo development
|
||||
environment, for writing, compiling and deploying our contracts to StarkNet.
|
||||
For the purpose of this tutorial we are going to be using the
|
||||
[Protostar Framework](https://github.com/software-mansion/protostar).
|
||||
Installation steps can be found in the docs
|
||||
[here](https://docs.swmansion.com/protostar/docs/tutorials/installation).
|
||||
Note that Protostar supports just Mac and Linux OS, Windows users might need to
|
||||
use WSL, or go for other alternatives such as the Official
|
||||
[StarkNet CLI](https://www.cairo-lang.org/docs/quickstart.html) or
|
||||
[Nile from Openzeppelin](https://github.com/OpenZeppelin/nile)
|
||||
|
||||
Once you're done with the installations, run the command `protostar -v` to
|
||||
confirm your installation was successful. If successful, you should see your
|
||||
Protostar version displayed on the screen.
|
||||
|
||||
## Initializing a new project
|
||||
|
||||
Protostar similar to Truffle for solidity development can be installed once and
|
||||
used for multiple projects. To initialize a new Protostar project, run the
|
||||
following command:
|
||||
|
||||
```
|
||||
protostar init
|
||||
```
|
||||
|
||||
It would then request the project's name and the library's directory name,
|
||||
you'd need to fill in this, and a new project will be initialized successfully.
|
||||
|
||||
## Compiling, Declaring, Deploying and Interacting with StarkNet Contracts
|
||||
|
||||
Within the `src` folder you'll find a boilerplate contract that comes with
|
||||
initializing a new Protostar project, `main.cairo`. We are going to be
|
||||
compiling, declaring and deploying this contract.
|
||||
|
||||
### Compiling Contracts
|
||||
|
||||
To compile a Cairo contract using Protostar, ensure a path to the contract is
|
||||
specified in the `[contracts]` section of the `protostar.toml` file. Once
|
||||
you've done that, open your terminal and run the command:
|
||||
|
||||
```
|
||||
protostar build
|
||||
```
|
||||
|
||||
And you should get an output similar to what you see below, with a `main.json`
|
||||
and `main_abi.json` files created in the `build` folder.
|
||||
<img src="./images/cairo/build.png" alt="building your contract">
|
||||
|
||||
### Declaring Contracts
|
||||
|
||||
With the recent StarkNet update to 0.10.3, the DEPLOY transaction was
|
||||
deprecated and no longer works. To deploy a transaction, you must first declare
|
||||
a Contract to obtain the class hash, then deploy the declared contract using the
|
||||
[Universal Deployer Contract](https://community.starknet.io/t/universal-deployer-contract-proposal/1864).
|
||||
|
||||
Before declaring or deploying your contract using Protostar, you should set the
|
||||
private key associated with the specified account address in a file, or in the
|
||||
terminal. To set your private key in the terminal, run the command:
|
||||
|
||||
```
|
||||
export PROTOSTAR_ACCOUNT_PRIVATE_KEY=[YOUR PRIVATE KEY HERE]
|
||||
```
|
||||
|
||||
Then to declare our contract using Protostar run the following command (for
|
||||
visual clarity, the backslash sign symbolizes the continuing line):
|
||||
|
||||
```
|
||||
protostar declare ./build/main.json \
|
||||
--network testnet \
|
||||
--account 0x0691622bBFD29e835bA4004e7425A4e9630840EbD11c5269DE51C16774585b16 \
|
||||
--max-fee auto
|
||||
```
|
||||
|
||||
where `network` specifies the network we are deploying to, `account` specifies
|
||||
account whose private key we are using, `max-fee` specifies the maximum fee to
|
||||
be paid for the transaction. You should get the class hash outputted as seen
|
||||
below:
|
||||
<img src="./images/cairo/declare.png" alt="declaring your contract">
|
||||
|
||||
### Deploying Contracts
|
||||
|
||||
After obtaining our class hash from declaring, we can now deploy using the
|
||||
command below:
|
||||
|
||||
```
|
||||
protostar \
|
||||
deploy 0x02a5de1b145e18dfeb31c7cd7ff403714ededf5f3fdf75f8b0ac96f2017541bc \
|
||||
--network testnet \
|
||||
--account 0x0691622bBFD29e835bA4004e7425A4e9630840EbD11c5269DE51C16774585b16 \
|
||||
--max-fee auto
|
||||
```
|
||||
|
||||
where `0x02a5de1b145e18dfeb31c7cd7ff403714ededf5f3fdf75f8b0ac96f2017541bc` is
|
||||
the class hash of our contract.
|
||||
<img src="./images/cairo/deploy.png" alt="deploying your contract">
|
||||
|
||||
### Interacting with Contracts
|
||||
|
||||
To interact with your deployed contract, we will be using `Argent X`
|
||||
(alternative: `Braavos`), and `Starkscan` (alternative: `Voyager`). To install
|
||||
and setup `Argent X`, see this
|
||||
[guide](https://www.argent.xyz/learn/how-to-create-an-argent-x-wallet/).
|
||||
|
||||
Copy your contract address, displayed on screen from the previous step, and
|
||||
head over to [Starkscan](https://testnet.starkscan.co/) to search for the
|
||||
contract. Once found, you can make write calls to the contract in the following
|
||||
sequence:
|
||||
|
||||
+ click on the "connect wallet" button,
|
||||
<img src="./images/cairo/connect.png" alt="connect wallet">
|
||||
+ select `Argent X` and approve the connection
|
||||
<img src="./images/cairo/connect2.png" alt="connect to argentX">
|
||||
+ you can now make read and write calls easily.
|
||||
|
||||
## Let's learn Cairo
|
||||
|
||||
First let's look at a default contract that comes with Protostar which allows
|
||||
you to set balance on deployment, increase, and get the balance.
|
||||
|
||||
```
|
||||
// Language directive - instructs compiler its a StarkNet contract
|
||||
%lang starknet
|
||||
|
||||
// Library imports from the Cairo-lang library
|
||||
from starkware.cairo.common.math import assert_nn
|
||||
from starkware.cairo.common.cairo_builtins import HashBuiltin
|
||||
|
||||
// @dev Storage variable that stores the balance of a user.
|
||||
// @storage_var is a decorator that instructs the compiler the function
|
||||
// below it is a storage variable.
|
||||
@storage_var
|
||||
func balance() -> (res: felt) {}
|
||||
|
||||
// @dev Constructor writes the balance variable to 0 on deployment
|
||||
// Constructors sets storage variables on deployment. Can accept arguments too.
|
||||
@constructor
|
||||
func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}() {
|
||||
balance.write(0);
|
||||
return();
|
||||
}
|
||||
|
||||
// @dev increase_balance updates the balance variable
|
||||
// @param amount the amount you want to add to balance
|
||||
// @external is a decorator that specifies the func below it is an external
|
||||
// function.
|
||||
@external
|
||||
func increase_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(amount: felt){
|
||||
with_attr error_message("Amount must be positive. Got: {amount}.") {
|
||||
assert_nn(amount);
|
||||
}
|
||||
|
||||
let (res) = balance.read();
|
||||
balance.write(res + amount);
|
||||
return ();
|
||||
}
|
||||
|
||||
// @dev returns the balance variable
|
||||
// @view is a decorator that specifies the func below it is a view function.
|
||||
@view
|
||||
func get_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}() -> (res: felt) {
|
||||
let (res) = balance.read();
|
||||
return (res,);
|
||||
}
|
||||
```
|
||||
|
||||
Before proceeding to the main lessons, try to build, deploy and interact with
|
||||
this contract.
|
||||
NB: You should be at `main.cairo` if you are using Protostar.
|
||||
|
||||
### 1. The Felt data type
|
||||
|
||||
Unlike solidity, where you have access to various data types, Cairo comes with
|
||||
just a single data type `..felts`. Felts stands for Field elements, and are a
|
||||
252 bit integer in the range `0<=x<=P` where `P` is a prime number. You can
|
||||
create a `Uint256` in Cairo by utlizing a struct of two 128 bits felts.
|
||||
|
||||
```
|
||||
struct Uint256 {
|
||||
low: felt, // The low 128 bits of the value.
|
||||
high: felt, // The high 128 bits of the value.
|
||||
}
|
||||
```
|
||||
|
||||
To avoid running into issues with divisions, it's safer to work with the
|
||||
`unsigned_div_rem` method from Cairo-lang's library.
|
||||
|
||||
### 2. Lang Directive and Imports
|
||||
|
||||
To get started with writing a StarkNet contract, you must specify the directive:
|
||||
|
||||
```
|
||||
%lang starknet
|
||||
```
|
||||
|
||||
This directive informs the compiler you are writing a contract and not a
|
||||
program. The difference between both is contracts have access to StarkNet's
|
||||
storage, programs don't and as such are stateless.
|
||||
|
||||
There are important functions you might need to import from the official
|
||||
Cairo-lang library or Openzeppelin's, e.g.
|
||||
|
||||
```
|
||||
from starkware.cairo.common.cairo_builtins import HashBuiltin
|
||||
from cairo_contracts.src.openzeppelin.token.erc20.library import ERC20
|
||||
from starkware.cairo.common.uint256 import Uint256
|
||||
from starkware.cairo.common.bool import TRUE
|
||||
```
|
||||
|
||||
### 3. Data Structures
|
||||
|
||||
+ Storage variables: Cairo's storage is a map with `2^251` slots, where each
|
||||
slot is a felt which is initialized to `0`. You create one using the
|
||||
`@storage_var` decorator.
|
||||
|
||||
```
|
||||
@storage_var
|
||||
func names() -> (name: felt) {}
|
||||
```
|
||||
|
||||
+ Storage mappings: Unlike Solidity where mappings have a separate keyword, in
|
||||
Cairo you create mappings using storage variables.
|
||||
|
||||
```
|
||||
@storage_var
|
||||
func names(address: felt) -> (name: felt) {}
|
||||
```
|
||||
|
||||
+ Structs: are a means to create custom data types in Cairo. A `struct` has a
|
||||
size, which is the sum of the sizes of its members. The size can be
|
||||
retrieved using `MyStruct.SIZE`. You create a struct in Cairo using the
|
||||
`struct` keyword.
|
||||
|
||||
```
|
||||
struct Person {
|
||||
name: felt,
|
||||
age: felt,
|
||||
address: felt,
|
||||
}
|
||||
```
|
||||
|
||||
+ Constants: Constants are fixed and as such can't be altered after being set.
|
||||
They evaluate to an integer (field element) at compile time. To create a
|
||||
constant in Cairo, you use the `const` keyword. It's proper practice to
|
||||
capitalize constant names.
|
||||
|
||||
```
|
||||
const USER = 0x01C6cfC1DB2ae90dACEA243F0a8C2F4e32560F7cDD398e4dA2Cc56B733774E9b
|
||||
```
|
||||
|
||||
+ Arrays: Arrays can be defined as a `pointer(felt*)` to the first element of
|
||||
the array. As an array is populated, its elements take up contigous memory
|
||||
cells. The `alloc` keyword can be used to dynamically allocate a new memory
|
||||
segment, which can be used to store an array:
|
||||
|
||||
```
|
||||
let (myArray: felt*) = alloc ();
|
||||
assert myArray[0] = 1;
|
||||
assert myArray[1] = 2;
|
||||
assert myArray[3] = 3;
|
||||
```
|
||||
|
||||
You can also use the `new` operator to create fixed-size arrays using
|
||||
tuples. The new operator is useful as it enables you allocate memory and
|
||||
initialize the object in one instruction
|
||||
|
||||
```
|
||||
func foo() {
|
||||
tempvar arr: felt* = new (1, 1, 2, 3, 5);
|
||||
assert arr[4] = 5;
|
||||
return ();
|
||||
}
|
||||
```
|
||||
|
||||
+ Tuples: A tuple is a finite, ordered, unchangeable list of elements. It is
|
||||
represented as a comma-separated list of elements enclosed by parentheses.
|
||||
Their elements may be of any combination of valid types.
|
||||
|
||||
```
|
||||
local tuple0: (felt, felt, felt) = (7, 9, 13);
|
||||
```
|
||||
|
||||
+ Events: Events allows a contract emit information during the course of its
|
||||
execution, that can be used outside of StarkNet. An event can be created,
|
||||
subsequently emitted:
|
||||
|
||||
```
|
||||
@event
|
||||
func name_stored(address, name) {}
|
||||
|
||||
name_stored.emit(address, name);
|
||||
```
|
||||
|
||||
### 4. Constructors, External and View functions
|
||||
|
||||
+ Constructors: Constructors are a way to intialize state variables on
|
||||
contract deployment. You create a constructor using the `@constructor`
|
||||
decorator.
|
||||
|
||||
```
|
||||
@constructor
|
||||
func constructor{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(_name: felt) {
|
||||
let (caller) = get_caller_address();
|
||||
names.write(caller, _name);
|
||||
return ();
|
||||
}
|
||||
```
|
||||
|
||||
+ External functions: External functions are functions that modifies the state
|
||||
of the network. You create an external function using the `@external`
|
||||
decorator:
|
||||
|
||||
```
|
||||
@external
|
||||
func store_name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(_name: felt){
|
||||
let (caller) = get_caller_address();
|
||||
names.write(caller, _name);
|
||||
stored_name.emit(caller, _name);
|
||||
return ();
|
||||
}
|
||||
```
|
||||
|
||||
+ View functions: View functions do not modify the state of the blockchain.
|
||||
You can create a view function using the `@view` decorator.
|
||||
|
||||
```
|
||||
@view
|
||||
func get_name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(_address: felt) -> (name: felt){
|
||||
let (name) = names.read(_address);
|
||||
return (name,);
|
||||
}
|
||||
```
|
||||
|
||||
NB: Unlike Solidity, Cairo supports just External and View function types.
|
||||
You can alternatively also create an internal function by not adding any
|
||||
decorator to the function.
|
||||
|
||||
### 5. Decorators
|
||||
|
||||
All functions in Cairo are specified by the `func` keyword, which can be
|
||||
confusing. Decorators are used by the compiler to distinguish between these
|
||||
functions.
|
||||
|
||||
Here are the most common decorators you'll encounter in Cairo:
|
||||
|
||||
+ `@storage_var` — used for specifying state variables.
|
||||
+ `@constructor` — used for specifying constructors.
|
||||
+ `@external` — used for specifying functions that write to a state variable.
|
||||
+ `@event` — used for specifying events
|
||||
+ `@view` — used to specify functions reading from a state variable
|
||||
+ `@contract_interface` — used for specifying function interfaces.
|
||||
+ `@l1_handler` — used for specifying functions that processes message sent from
|
||||
an L1 contract in a messaging bridge.
|
||||
|
||||
### 6. BUILTINS, HINTS & IMPLICIT Arguments
|
||||
|
||||
+ `BUILTINS` are predefined optimized low-level execution units, which are
|
||||
added to Cairo’s CPU board. They help perform predefined computations like
|
||||
pedersen hashing, bitwise operations etc, which are expensive to perform in
|
||||
Vanilla Cairo. Each builtin in Cairo is assigned a separate memory location,
|
||||
accessible through regular Cairo memory calls using implicit parameters. You
|
||||
specify them using the `%builtins` directive
|
||||
|
||||
Here is a list of available builtins in Cairo:
|
||||
|
||||
+ `output` — the output builtin is used for writing program outputs
|
||||
+ `pedersen` — the pedersen builtin is used for pedersen hashing
|
||||
computations
|
||||
+ `range_check` — This builtin is mostly used for integer comparisons,
|
||||
and facilitates check to confirm that a field element is within a range
|
||||
`[0, 2^128)`
|
||||
+ `ecdsa` — the ecdsa builtin is used for verifying ECDSA signatures
|
||||
+ `bitwise` — the bitwise builtin is used for carrying out bitwise
|
||||
operations on felts
|
||||
|
||||
+ `HINTS` are pieces of Python codes, which contains instructions that only
|
||||
the prover sees and executes. From the point of view of the verifier these
|
||||
hints do not exist. To specify a hint in Cairo, you need to encapsulate it
|
||||
within `%{` and `%}`. It is good practice to avoid using hints as much as
|
||||
you can in your contracts, as hints are not added to the bytecode, and thus
|
||||
do not count in the total number of execution steps.
|
||||
|
||||
```
|
||||
%{
|
||||
# Python hint goes here
|
||||
%}
|
||||
```
|
||||
|
||||
+ `IMPLICIT ARGUMENTS` are not restricted to the function body, but can be
|
||||
inherited by other functions calls that require them. Implicit arguments are
|
||||
passed in between curly bracelets, like you can see below:
|
||||
|
||||
```
|
||||
func store_name{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(_name: felt){
|
||||
let (caller) = get_caller_address();
|
||||
names.write(caller, _name);
|
||||
stored_name.emit(caller, _name);
|
||||
return ();
|
||||
}
|
||||
```
|
||||
|
||||
### 7. Error Messages and Access Controls
|
||||
|
||||
You can create custom errors in Cairo which is outputted to the user upon failed
|
||||
execution. This can be very useful for implementing checks and proper access
|
||||
control mechanisms. An example is preventing a user to call a function except
|
||||
user is `admin`.
|
||||
|
||||
```
|
||||
// imports
|
||||
from starkware.starknet.common.syscalls import get_caller_address
|
||||
|
||||
// create an admin constant
|
||||
const ADMIN = 0x01C6cfC1DB2ae90dACEA243F0a8C2F4e32560F7cDD398e4dA2Cc56B733774E9b
|
||||
|
||||
// implement access control
|
||||
with_attr error_message("You do not have access to make this action!"){
|
||||
let (caller) = get_caller_address();
|
||||
assert ADMIN = caller;
|
||||
}
|
||||
|
||||
// using an assert statement throws if condition is not true, thus
|
||||
// returning the specified error.
|
||||
```
|
||||
|
||||
### 8. Contract Interfaces
|
||||
|
||||
Contract interfaces provide a means for one contract to invoke or call the
|
||||
external function of another contract. To create a contract interface, you use
|
||||
the `@contract_interface` keyword:
|
||||
|
||||
```
|
||||
@contract_interface
|
||||
namespace IENS {
|
||||
func store_name(_name: felt) {
|
||||
}
|
||||
|
||||
func get_name(_address: felt) -> (name: felt) {
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Once a contract interface is specified, any contract can make calls to that
|
||||
contract passing in the contract address as the first parameter like this:
|
||||
|
||||
```
|
||||
IENS.store_name(contract_address, _name);
|
||||
```
|
||||
|
||||
Note that Interfaces exclude the function body/logic and the implicit
|
||||
arguments.
|
||||
|
||||
### 9. Recursions
|
||||
|
||||
Due to the unavailability of loops, Recursion is the go-to for similar
|
||||
operations. In simple terms, a recursive function is one which calls itself
|
||||
repeatedly.
|
||||
|
||||
A good example to demonstrate this is writing a function for getting the nth
|
||||
fibonacci number:
|
||||
|
||||
```
|
||||
@external
|
||||
func fibonacci{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(n : felt) -> (result : felt){
|
||||
alloc_locals;
|
||||
if (n == 0){
|
||||
return (0);
|
||||
}
|
||||
if (n == 1){
|
||||
return (1);
|
||||
}
|
||||
let (local x) = fibonacci(n - 1);
|
||||
let (local y) = fibonacci(n - 2);
|
||||
return (result=(x + y));
|
||||
}
|
||||
```
|
||||
|
||||
The nth fibonacci term is the sum of the `nth - 1` and the `nth - 2` numbers,
|
||||
that's why we get these two as `(x,y)` using recursion.
|
||||
|
||||
NB: when implementing recursive functions, always remember to implement a base
|
||||
case (`n==0`, `n==1` in our case), to prevent stack overflows.
|
||||
|
||||
### 10. Registers
|
||||
|
||||
Registers holds values that may change over time. There are 3 major types of
|
||||
registers:
|
||||
|
||||
+ `ap` (allocation pointer) points to a yet unused memory. Temporary variables
|
||||
created using `let`, `tempvar` are held here, and thus susceptible to being
|
||||
revoked.
|
||||
+ `fp` (frame pointer) points to the frame of the current function. The address
|
||||
of all the function arguments and local variables are relative to this
|
||||
register and as such can never be revoked.
|
||||
+ `pc` (program counter) points to the current instruction.
|
||||
|
||||
### 11. Revoked References
|
||||
|
||||
Revoked references occur when there is a call instruction to another function,
|
||||
between the definition of a reference variable that depends on `ap` (temp
|
||||
variables) and its usage. This occurs as the compiler may not be able to compute
|
||||
the change of `ap` (as one may jump to the label from another place in the
|
||||
program, or call a function that might change ap in an unknown way).
|
||||
|
||||
Here is an example to demonstrate what I mean:
|
||||
|
||||
```
|
||||
@external
|
||||
func get_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}() -> (res: felt) {
|
||||
return (res=100);
|
||||
}
|
||||
|
||||
@external
|
||||
func double_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}() -> (res: felt) {
|
||||
let multiplier = 2;
|
||||
let (balance) = get_balance();
|
||||
let new_balance = balance * multiplier;
|
||||
return (res=new_balance);
|
||||
}
|
||||
```
|
||||
|
||||
If you run that code, you'll run into the revoked reference error as we are
|
||||
trying to access the `multiplier` variable after calling the `get_balance`
|
||||
function.
|
||||
|
||||
In simple cases you can resolve revoked references by adding the keyword
|
||||
`alloc_locals` within function scopes. In more complex cases you might need to
|
||||
create a local variable to resolve it.
|
||||
|
||||
```
|
||||
// resolving the `double_balance` function:
|
||||
@external
|
||||
func double_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}() -> (res: felt) {
|
||||
alloc_locals;
|
||||
let multiplier = 2;
|
||||
let (balance) = get_balance();
|
||||
let new_balance = balance * multiplier;
|
||||
return (res=new_balance);
|
||||
}
|
||||
```
|
||||
|
||||
### 12. Understanding Cairo's Punctuations
|
||||
|
||||
+ `;` (semicolon). Used at the end of each instruction
|
||||
+ `()` (parentheses). Used in a function declaration, if statements, and in a
|
||||
tuple declaration
|
||||
+ `{}` (curly braces). Used in a declaration of implicit arguments and to define
|
||||
code blocks.
|
||||
+ `[]` (square brackets). Standalone brackets represent the value at a
|
||||
particular address location (such as the allocation pointer, `[ap]`). Brackets
|
||||
following a pointer or a tuple act as a subscript operator, where `x[2]`
|
||||
represents the element with index `2` in `x`.
|
||||
+ `*` (single asterisk). Refers to the pointer of an expression.
|
||||
+ `%` (percent sign). Appears at the start of a directive, such as `%builtins`
|
||||
or `%lang`.
|
||||
+ `%{` and `%}` represent Python hints.
|
||||
+ `_` (underscore). A placeholder to handle values that are not used, such as an
|
||||
unused function return value.
|
||||
|
||||
## Full Contract Example
|
||||
|
||||
Below is a simple automated market maker contract example that implements most
|
||||
of what we just learnt! Re-write, deploy, have fun!
|
||||
|
||||
```
|
||||
%lang starknet
|
||||
|
||||
from starkware.cairo.common.cairo_builtins import HashBuiltin
|
||||
from starkware.cairo.common.hash import hash2
|
||||
from starkware.cairo.common.alloc import alloc
|
||||
from starkware.cairo.common.math import (assert_le, assert_nn_le,
|
||||
unsigned_div_rem)
|
||||
from starkware.starknet.common.syscalls import (get_caller_address,
|
||||
storage_read, storage_write)
|
||||
|
||||
|
||||
// CONSTANTS
|
||||
//
|
||||
// @dev the maximum amount of each token that belongs to the AMM
|
||||
const BALANCE_UPPER_BOUND = 2 ** 64;
|
||||
|
||||
const TOKEN_TYPE_A = 1;
|
||||
const TOKEN_TYPE_B = 2;
|
||||
|
||||
// @dev Ensure the user's balances are much smaller than the pool's balance
|
||||
const POOL_UPPER_BOUND = 2 ** 30;
|
||||
const ACCOUNT_BALANCE_BOUND = 1073741; // (2 ** 30 / 1000)
|
||||
|
||||
|
||||
// STORAGE VARIABLES
|
||||
//
|
||||
// @dev A map from account and token type to corresponding balance
|
||||
@storage_var
|
||||
func account_balance(account_id: felt, token_type: felt) -> (balance: felt) {}
|
||||
|
||||
// @dev a map from token type to corresponding pool balance
|
||||
@storage_var
|
||||
func pool_balance(token_type: felt) -> (balance: felt) {}
|
||||
|
||||
|
||||
// GETTERS
|
||||
//
|
||||
// @dev returns account balance for a given token
|
||||
// @param account_id Account to be queried
|
||||
// @param token_type Token to be queried
|
||||
@view
|
||||
func get_account_token_balance{syscall_ptr: felt*, pedersen_ptr:
|
||||
HashBuiltin*, range_check_ptr}(
|
||||
account_id: felt, token_type: felt
|
||||
) -> (balance: felt) {
|
||||
return account_balance.read(account_id, token_type);
|
||||
}
|
||||
|
||||
// @dev return the pool's balance
|
||||
// @param token_type Token type to get pool balance
|
||||
@view
|
||||
func get_pool_token_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
token_type: felt
|
||||
) -> (balance: felt) {
|
||||
return pool_balance.read(token_type);
|
||||
}
|
||||
|
||||
|
||||
// EXTERNALS
|
||||
//
|
||||
// @dev set pool balance for a given token
|
||||
// @param token_type Token whose balance is to be set
|
||||
// @param balance Amount to be set as balance
|
||||
@external
|
||||
func set_pool_token_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
token_type: felt, balance: felt
|
||||
) {
|
||||
with_attr error_message("exceeds maximum allowed tokens!"){
|
||||
assert_nn_le(balance, BALANCE_UPPER_BOUND - 1);
|
||||
}
|
||||
|
||||
pool_balance.write(token_type, balance);
|
||||
return ();
|
||||
}
|
||||
|
||||
// @dev add demo token to the given account
|
||||
// @param token_a_amount amount of token a to be added
|
||||
// @param token_b_amount amount of token b to be added
|
||||
@external
|
||||
func add_demo_token{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
token_a_amount: felt, token_b_amount: felt
|
||||
) {
|
||||
alloc_locals;
|
||||
let (account_id) = get_caller_address();
|
||||
|
||||
modify_account_balance(account_id=account_id, token_type=TOKEN_TYPE_A,
|
||||
amount=token_a_amount);
|
||||
modify_account_balance(account_id=account_id, token_type=TOKEN_TYPE_B,
|
||||
amount=token_b_amount);
|
||||
|
||||
return ();
|
||||
}
|
||||
|
||||
// @dev intialize AMM
|
||||
// @param token_a amount of token a to be set in pool
|
||||
// @param token_b amount of token b to be set in pool
|
||||
@external
|
||||
func init_pool{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
token_a: felt, token_b: felt
|
||||
) {
|
||||
with_attr error_message("exceeds maximum allowed tokens!"){
|
||||
assert_nn_le(token_a, POOL_UPPER_BOUND - 1);
|
||||
assert_nn_le(token_b, POOL_UPPER_BOUND - 1);
|
||||
}
|
||||
|
||||
set_pool_token_balance(token_type=TOKEN_TYPE_A, balance=token_a);
|
||||
set_pool_token_balance(token_type=TOKEN_TYPE_B, balance=token_b);
|
||||
|
||||
return ();
|
||||
}
|
||||
|
||||
|
||||
// @dev swaps token between the given account and the pool
|
||||
// @param token_from token to be swapped
|
||||
// @param amount_from amount of token to be swapped
|
||||
// @return amount_to the token swapped to
|
||||
@external
|
||||
func swap{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*, range_check_ptr}(
|
||||
token_from: felt, amount_from: felt
|
||||
) -> (amount_to: felt) {
|
||||
alloc_locals;
|
||||
let (account_id) = get_caller_address();
|
||||
|
||||
// verify token_from is TOKEN_TYPE_A or TOKEN_TYPE_B
|
||||
with_attr error_message("token not allowed in pool!"){
|
||||
assert (token_from - TOKEN_TYPE_A) * (token_from - TOKEN_TYPE_B) = 0;
|
||||
}
|
||||
|
||||
// check requested amount_from is valid
|
||||
with_attr error_message("exceeds maximum allowed tokens!"){
|
||||
assert_nn_le(amount_from, BALANCE_UPPER_BOUND - 1);
|
||||
}
|
||||
|
||||
// check user has enough funds
|
||||
let (account_from_balance) =
|
||||
get_account_token_balance(account_id=account_id, token_type=token_from);
|
||||
with_attr error_message("insufficient balance!"){
|
||||
assert_le(amount_from, account_from_balance);
|
||||
}
|
||||
|
||||
let (token_to) = get_opposite_token(token_type=token_from);
|
||||
let (amount_to) = do_swap(account_id=account_id, token_from=token_from,
|
||||
token_to=token_to, amount_from=amount_from);
|
||||
|
||||
return (amount_to=amount_to);
|
||||
}
|
||||
|
||||
|
||||
// INTERNALS
|
||||
//
|
||||
// @dev internal function that updates account balance for a given token
|
||||
// @param account_id Account whose balance is to be modified
|
||||
// @param token_type Token type to be modified
|
||||
// @param amount Amount Amount to be added
|
||||
func modify_account_balance{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
account_id: felt, token_type: felt, amount: felt
|
||||
) {
|
||||
let (current_balance) = account_balance.read(account_id, token_type);
|
||||
tempvar new_balance = current_balance + amount;
|
||||
|
||||
with_attr error_message("exceeds maximum allowed tokens!"){
|
||||
assert_nn_le(new_balance, BALANCE_UPPER_BOUND - 1);
|
||||
}
|
||||
|
||||
account_balance.write(account_id=account_id, token_type=token_type,
|
||||
value=new_balance);
|
||||
return ();
|
||||
}
|
||||
|
||||
// @dev internal function that swaps tokens between the given account and
|
||||
// the pool
|
||||
// @param account_id Account whose tokens are to be swapped
|
||||
// @param token_from Token type to be swapped from
|
||||
// @param token_to Token type to be swapped to
|
||||
// @param amount_from Amount to be swapped
|
||||
func do_swap{syscall_ptr: felt*, pedersen_ptr: HashBuiltin*,
|
||||
range_check_ptr}(
|
||||
account_id: felt, token_from: felt, token_to: felt, amount_from: felt
|
||||
) -> (amount_to: felt) {
|
||||
alloc_locals;
|
||||
|
||||
// get pool balance
|
||||
let (local amm_from_balance) = get_pool_token_balance(token_type =
|
||||
token_from);
|
||||
let (local amm_to_balance) = get_pool_token_balance(token_type=token_to);
|
||||
|
||||
// calculate swap amount
|
||||
let (local amount_to, _) = unsigned_div_rem((amm_to_balance *
|
||||
amount_from), (amm_from_balance + amount_from));
|
||||
|
||||
// update token_from balances
|
||||
modify_account_balance(account_id=account_id, token_type=token_from,
|
||||
amount=-amount_from);
|
||||
set_pool_token_balance(token_type=token_from, balance=(amm_from_balance
|
||||
+ amount_from));
|
||||
|
||||
// update token_to balances
|
||||
modify_account_balance(account_id=account_id, token_type=token_to,
|
||||
amount=amount_to);
|
||||
set_pool_token_balance(token_type=token_to, balance=(amm_to_balance -
|
||||
amount_to));
|
||||
|
||||
return (amount_to=amount_to);
|
||||
}
|
||||
|
||||
|
||||
// @dev internal function to get the opposite token type
|
||||
// @param token_type Token whose opposite pair needs to be gotten
|
||||
func get_opposite_token(token_type: felt) -> (t: felt) {
|
||||
if(token_type == TOKEN_TYPE_A) {
|
||||
return (t=TOKEN_TYPE_B);
|
||||
} else {
|
||||
return (t=TOKEN_TYPE_A);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Additional Resources
|
||||
|
||||
+ [Official documentation](https://www.cairo-lang.org/docs/)
|
||||
+ [Starknet EDU](https://medium.com/starknet-edu)
|
||||
+ [Journey through Cairo](https://medium.com/@darlingtonnnam/journey-through-cairo-i-setting-up-protostar-and-argentx-for-local-development-ba40ae6c5524)
|
||||
+ [Demystifying Cairo whitepaper](https://medium.com/@pban/demystifying-cairo-white-paper-part-i-b71976ad0108)
|
||||
+ [Learn about StarkNet with Argent](https://www.argent.xyz/learn/tag/starknet/)
|
||||
|
||||
## Development Frameworks
|
||||
|
||||
+ [Protostar](https://docs.swmansion.com/protostar/docs/tutorials/installation)
|
||||
+ [Nile](https://github.com/OpenZeppelin/nile)
|
||||
+ [StarkNet CLI](https://www.cairo-lang.org/docs/quickstart.html)
|
||||
|
||||
## Helpful Libraries
|
||||
|
||||
+ [Cairo-lang](https://github.com/starkware-libs/cairo-lang)
|
||||
+ [Openzeppelin](https://github.com/OpenZeppelin/cairo-contracts)
|
||||
|
||||
## Educational Repos
|
||||
|
||||
+ [StarkNet Cairo 101](https://github.com/starknet-edu/starknet-cairo-101)
|
||||
+ [StarkNet ERC721](https://github.com/starknet-edu/starknet-erc721)
|
||||
+ [StarkNet ERC20](https://github.com/starknet-edu/starknet-erc20)
|
||||
+ [L1 -> L2 Messaging](https://github.com/starknet-edu/starknet-messaging-bridge)
|
||||
+ [StarkNet Debug](https://github.com/starknet-edu/starknet-debug)
|
||||
+ [StarkNet Accounts](https://github.com/starknet-edu/starknet-accounts)
|
||||
+ [Min-Starknet](https://github.com/Darlington02/min-starknet)
|
||||
|
||||
## Security
|
||||
|
||||
+ [Amarna static analysis for Cairo programs](https://blog.trailofbits.com/2022/04/20/amarna-static-analysis-for-cairo-programs/)
|
||||
+ [Cairo and StarkNet security by Ctrl03](https://ctrlc03.github.io/)
|
||||
+ [How to hack almost any Cairo smart contract](https://medium.com/ginger-security/how-to-hack-almost-any-starknet-cairo-smart-contract-67b4681ac0f6)
|
||||
+ [Analyzing Cairo code using Armana](https://dic0de.substack.com/p/analyzing-cairo-code-using-amarna?sd=pf)
|
||||
|
||||
## Future TO-DOs
|
||||
|
||||
Update tutorial to fit Cairo 1.0
|
@ -13,42 +13,60 @@ as well as multi-kilocore supercomputers.
|
||||
|
||||
More information and support can be found at the bottom of this document.
|
||||
|
||||
You can refer to the official site for [latest version](https://chapel-lang.org/docs/master/primers/learnChapelInYMinutes.html) of this document.
|
||||
|
||||
```chapel
|
||||
/*
|
||||
Learn Chapel in Y Minutes
|
||||
|
||||
This primer will go over basic syntax and concepts in Chapel.
|
||||
Last sync with official page: Sun, 08 Mar 2020 08:05:53 +0000
|
||||
*/
|
||||
|
||||
// Comments are C-family style
|
||||
|
||||
// one line comment
|
||||
/*
|
||||
multi-line comment
|
||||
multi-line comment
|
||||
*/
|
||||
|
||||
// Basic printing
|
||||
/*
|
||||
Basic printing
|
||||
*/
|
||||
|
||||
write("Hello, ");
|
||||
writeln("World!");
|
||||
|
||||
// write and writeln can take a list of things to print.
|
||||
// ``write`` and ``writeln`` can take a list of things to print.
|
||||
// Each thing is printed right next to the others, so include your spacing!
|
||||
writeln("There are ", 3, " commas (\",\") in this line of code");
|
||||
|
||||
// Different output channels:
|
||||
use IO; // Required for accessing the alternative output channels
|
||||
|
||||
stdout.writeln("This goes to standard output, just like plain writeln() does");
|
||||
stderr.writeln("This goes to standard error");
|
||||
|
||||
/*
|
||||
Variables
|
||||
*/
|
||||
|
||||
// Variables don't have to be explicitly typed as long as
|
||||
// the compiler can figure out the type that it will hold.
|
||||
// 10 is an int, so myVar is implicitly an int
|
||||
// 10 is an ``int``, so ``myVar`` is implicitly an ``int``
|
||||
var myVar = 10;
|
||||
myVar = -10;
|
||||
var mySecondVar = myVar;
|
||||
// var anError; would be a compile-time error.
|
||||
// ``var anError;`` would be a compile-time error.
|
||||
|
||||
// We can (and should) explicitly type things.
|
||||
var myThirdVar: real;
|
||||
var myFourthVar: real = -1.234;
|
||||
myThirdVar = myFourthVar;
|
||||
|
||||
// Types
|
||||
/*
|
||||
Types
|
||||
*/
|
||||
|
||||
// There are a number of basic types.
|
||||
var myInt: int = -1000; // Signed ints
|
||||
@ -75,39 +93,45 @@ type RGBColor = 3*chroma; // Type representing a full color
|
||||
var black: RGBColor = (0,0,0);
|
||||
var white: RGBColor = (255, 255, 255);
|
||||
|
||||
// Constants and Parameters
|
||||
/*
|
||||
Constants and Parameters
|
||||
*/
|
||||
|
||||
// A const is a constant, and cannot be changed after set in runtime.
|
||||
// A ``const`` is a constant, and cannot be changed after set in runtime.
|
||||
const almostPi: real = 22.0/7.0;
|
||||
|
||||
// A param is a constant whose value must be known statically at
|
||||
// A ``param`` is a constant whose value must be known statically at
|
||||
// compile-time.
|
||||
param compileTimeConst: int = 16;
|
||||
|
||||
// The config modifier allows values to be set at the command line.
|
||||
// Set with --varCmdLineArg=Value or --varCmdLineArg Value at runtime.
|
||||
// The ``config`` modifier allows values to be set at the command line.
|
||||
// Set with ``--varCmdLineArg=Value`` or ``--varCmdLineArg Value`` at runtime.
|
||||
config var varCmdLineArg: int = -123;
|
||||
config const constCmdLineArg: int = 777;
|
||||
|
||||
// config param can be set at compile-time.
|
||||
// Set with --set paramCmdLineArg=value at compile-time.
|
||||
// ``config param`` can be set at compile-time.
|
||||
// Set with ``--set paramCmdLineArg=value`` at compile-time.
|
||||
config param paramCmdLineArg: bool = false;
|
||||
writeln(varCmdLineArg, ", ", constCmdLineArg, ", ", paramCmdLineArg);
|
||||
|
||||
// References
|
||||
/*
|
||||
References
|
||||
*/
|
||||
|
||||
// ref operates much like a reference in C++. In Chapel, a ref cannot
|
||||
// ``ref`` operates much like a reference in C++. In Chapel, a ``ref`` cannot
|
||||
// be made to alias a variable other than the variable it is initialized with.
|
||||
// Here, refToActual refers to actual.
|
||||
// Here, ``refToActual`` refers to ``actual``.
|
||||
var actual = 10;
|
||||
ref refToActual = actual;
|
||||
ref refToActual = actual;
|
||||
writeln(actual, " == ", refToActual); // prints the same value
|
||||
actual = -123; // modify actual (which refToActual refers to)
|
||||
writeln(actual, " == ", refToActual); // prints the same value
|
||||
refToActual = 99999999; // modify what refToActual refers to (which is actual)
|
||||
writeln(actual, " == ", refToActual); // prints the same value
|
||||
|
||||
// Operators
|
||||
/*
|
||||
Operators
|
||||
*/
|
||||
|
||||
// Math operators:
|
||||
var a: int, thisInt = 1234, thatInt = 5678;
|
||||
@ -146,7 +170,7 @@ a <<= 3; // Left-bit-shift-equals (a = a << 10;)
|
||||
// Unlike other C family languages, there are no
|
||||
// pre/post-increment/decrement operators, such as:
|
||||
//
|
||||
// ++j, --j, j++, j--
|
||||
// ``++j``, ``--j``, ``j++``, ``j--``
|
||||
|
||||
// Swap operator:
|
||||
var old_this = thisInt;
|
||||
@ -156,7 +180,9 @@ writeln((old_this == thatInt) && (old_that == thisInt));
|
||||
|
||||
// Operator overloads can also be defined, as we'll see with procedures.
|
||||
|
||||
// Tuples
|
||||
/*
|
||||
Tuples
|
||||
*/
|
||||
|
||||
// Tuples can be of the same type or different types.
|
||||
var sameTup: 2*int = (10, -1);
|
||||
@ -179,16 +205,18 @@ writeln(diffTup == (tupInt, tupReal, tupCplx));
|
||||
// They are also useful for writing a list of variables, as is common in debugging.
|
||||
writeln((a,b,thisInt,thatInt,thisBool,thatBool));
|
||||
|
||||
// Control Flow
|
||||
/*
|
||||
Control Flow
|
||||
*/
|
||||
|
||||
// if - then - else works just like any other C-family language.
|
||||
// ``if`` - ``then`` - ``else`` works just like any other C-family language.
|
||||
if 10 < 100 then
|
||||
writeln("All is well");
|
||||
|
||||
if -1 < 1 then
|
||||
writeln("Continuing to believe reality");
|
||||
else
|
||||
writeln("Send mathematician, something is wrong");
|
||||
writeln("Send mathematician, something's wrong");
|
||||
|
||||
// You can use parentheses if you prefer.
|
||||
if (10 > 100) {
|
||||
@ -209,11 +237,11 @@ if a % 3 == 0 {
|
||||
writeln(b, " is divided by 3 with a remainder of 2.");
|
||||
}
|
||||
|
||||
// Ternary: if - then - else in a statement.
|
||||
// Ternary: ``if`` - ``then`` - ``else`` in a statement.
|
||||
var maximum = if thisInt < thatInt then thatInt else thisInt;
|
||||
|
||||
// select statements are much like switch statements in other languages.
|
||||
// However, select statements do not cascade like in C or Java.
|
||||
// ``select`` statements are much like switch statements in other languages.
|
||||
// However, ``select`` statements don't cascade like in C or Java.
|
||||
var inputOption = "anOption";
|
||||
select inputOption {
|
||||
when "anOption" do writeln("Chose 'anOption'");
|
||||
@ -223,11 +251,11 @@ select inputOption {
|
||||
}
|
||||
otherwise {
|
||||
writeln("Any other Input");
|
||||
writeln("the otherwise case does not need a do if the body is one line");
|
||||
writeln("the otherwise case doesn't need a do if the body is one line");
|
||||
}
|
||||
}
|
||||
|
||||
// while and do-while loops also behave like their C counterparts.
|
||||
// ``while`` and ``do``-``while`` loops also behave like their C counterparts.
|
||||
var j: int = 1;
|
||||
var jSum: int = 0;
|
||||
while (j <= 1000) {
|
||||
@ -242,8 +270,8 @@ do {
|
||||
} while (j <= 10000);
|
||||
writeln(jSum);
|
||||
|
||||
// for loops are much like those in Python in that they iterate over a
|
||||
// range. Ranges (like the 1..10 expression below) are a first-class object
|
||||
// ``for`` loops are much like those in python in that they iterate over a
|
||||
// range. Ranges (like the ``1..10`` expression below) are a first-class object
|
||||
// in Chapel, and as such can be stored in variables.
|
||||
for i in 1..10 do write(i, ", ");
|
||||
writeln();
|
||||
@ -261,7 +289,9 @@ for x in 1..10 {
|
||||
writeln();
|
||||
}
|
||||
|
||||
// Ranges and Domains
|
||||
/*
|
||||
Ranges and Domains
|
||||
*/
|
||||
|
||||
// For-loops and arrays both use ranges and domains to define an index set that
|
||||
// can be iterated over. Ranges are single dimensional integer indices, while
|
||||
@ -277,17 +307,18 @@ var rangeEmpty: range = 100..-100; // this is valid but contains no indices
|
||||
var range1toInf: range(boundedType=BoundedRangeType.boundedLow) = 1.. ; // 1, 2, 3, 4, 5, ...
|
||||
var rangeNegInfTo1 = ..1; // ..., -4, -3, -2, -1, 0, 1
|
||||
|
||||
// Ranges can be strided (and reversed) using the by operator.
|
||||
// Ranges can be strided (and reversed) using the ``by`` operator.
|
||||
var range2to10by2: range(stridable=true) = 2..10 by 2; // 2, 4, 6, 8, 10
|
||||
var reverse2to10by2 = 2..10 by -2; // 10, 8, 6, 4, 2
|
||||
|
||||
var trapRange = 10..1 by -1; // Do not be fooled, this is still an empty range
|
||||
writeln("Size of range ", trapRange, " = ", trapRange.length);
|
||||
writeln("Size of range '", trapRange, "' = ", trapRange.size);
|
||||
|
||||
// Note: range(boundedType= ...) and range(stridable= ...) are only
|
||||
// Note: ``range(boundedType= ...)`` and ``range(stridable= ...)`` are only
|
||||
// necessary if we explicitly type the variable.
|
||||
|
||||
// The end point of a range can be determined using the count (#) operator.
|
||||
// The end point of a range can be computed by specifying the total size
|
||||
// of the range using the count (``#``) operator.
|
||||
var rangeCount: range = -5..#12; // range from -5 to 6
|
||||
|
||||
// Operators can be mixed.
|
||||
@ -297,8 +328,8 @@ writeln(rangeCountBy);
|
||||
// Properties of the range can be queried.
|
||||
// In this example, printing the first index, last index, number of indices,
|
||||
// stride, and if 2 is include in the range.
|
||||
writeln((rangeCountBy.first, rangeCountBy.last, rangeCountBy.length,
|
||||
rangeCountBy.stride, rangeCountBy.member(2)));
|
||||
writeln((rangeCountBy.first, rangeCountBy.last, rangeCountBy.size,
|
||||
rangeCountBy.stride, rangeCountBy.contains(2)));
|
||||
|
||||
for i in rangeCountBy {
|
||||
write(i, if i == rangeCountBy.last then "\n" else ", ");
|
||||
@ -322,7 +353,7 @@ for idx in twoDimensions do
|
||||
write(idx, ", ");
|
||||
writeln();
|
||||
|
||||
// These tuples can also be deconstructed.
|
||||
// These tuples can also be destructured.
|
||||
for (x,y) in twoDimensions {
|
||||
write("(", x, ", ", y, ")", ", ");
|
||||
}
|
||||
@ -352,7 +383,9 @@ var domainB = {-5..5, 1..10};
|
||||
var domainC = domainA[domainB];
|
||||
writeln((domainA, domainB, domainC));
|
||||
|
||||
// Arrays
|
||||
/*
|
||||
Arrays
|
||||
*/
|
||||
|
||||
// Arrays are similar to those of other languages.
|
||||
// Their sizes are defined using domains that represent their indices.
|
||||
@ -364,9 +397,9 @@ for i in 1..10 do
|
||||
intArray[i] = -i;
|
||||
writeln(intArray);
|
||||
|
||||
// We cannot access intArray[0] because it exists outside
|
||||
// of the index set, {1..10}, we defined it to have.
|
||||
// intArray[11] is illegal for the same reason.
|
||||
// We cannot access ``intArray[0]`` because it exists outside
|
||||
// of the index set, ``{1..10}``, we defined it to have.
|
||||
// ``intArray[11]`` is illegal for the same reason.
|
||||
var realDomain: domain(2) = {1..5,1..7};
|
||||
var realArray: [realDomain] real;
|
||||
var realArray2: [1..5,1..7] real; // equivalent
|
||||
@ -396,9 +429,9 @@ for value in realArray {
|
||||
writeln(rSum, "\n", realArray);
|
||||
|
||||
// Associative arrays (dictionaries) can be created using associative domains.
|
||||
var dictDomain: domain(string) = { "one", "two" };
|
||||
var dict: [dictDomain] int = ["one" => 1, "two" => 2];
|
||||
dict["three"] = 3; // Adds 'three' to 'dictDomain' implicitly
|
||||
var dictDomain: domain(string) = { "one", "two", "three"};
|
||||
var dict: [dictDomain] int = ["one" => 1, "two" => 2, "three" => 3];
|
||||
|
||||
for key in dictDomain.sorted() do
|
||||
writeln(dict[key]);
|
||||
|
||||
@ -407,9 +440,9 @@ for key in dictDomain.sorted() do
|
||||
var thisArray : [0..5] int = [0,1,2,3,4,5];
|
||||
var thatArray : [0..5] int;
|
||||
|
||||
// First, simply assign one to the other. This copies thisArray into
|
||||
// thatArray, instead of just creating a reference. Therefore, modifying
|
||||
// thisArray does not also modify thatArray.
|
||||
// First, simply assign one to the other. This copies ``thisArray`` into
|
||||
// ``thatArray``, instead of just creating a reference. Therefore, modifying
|
||||
// ``thisArray`` does not also modify ``thatArray``.
|
||||
|
||||
thatArray = thisArray;
|
||||
thatArray[1] = -1;
|
||||
@ -425,7 +458,7 @@ var thisPlusThat = thisArray + thatArray;
|
||||
writeln(thisPlusThat);
|
||||
|
||||
// Moving on, arrays and loops can also be expressions, where the loop
|
||||
// body expression is the result of each iteration.
|
||||
// body's expression is the result of each iteration.
|
||||
var arrayFromLoop = for i in 1..10 do i;
|
||||
writeln(arrayFromLoop);
|
||||
|
||||
@ -435,16 +468,18 @@ var evensOrFives = for i in 1..10 do if (i % 2 == 0 || i % 5 == 0) then i;
|
||||
writeln(arrayFromLoop);
|
||||
|
||||
// Array expressions can also be written with a bracket notation.
|
||||
// Note: this syntax uses the forall parallel concept discussed later.
|
||||
// Note: this syntax uses the ``forall`` parallel concept discussed later.
|
||||
var evensOrFivesAgain = [i in 1..10] if (i % 2 == 0 || i % 5 == 0) then i;
|
||||
|
||||
// They can also be written over the values of the array.
|
||||
arrayFromLoop = [value in arrayFromLoop] value + 1;
|
||||
|
||||
|
||||
// Procedures
|
||||
/*
|
||||
Procedures
|
||||
*/
|
||||
|
||||
// Chapel procedures have similar syntax functions in other languages.
|
||||
// Chapel procedures have similar syntax functions in other languages.
|
||||
proc fibonacci(n : int) : int {
|
||||
if n <= 1 then return n;
|
||||
return fibonacci(n-1) + fibonacci(n-2);
|
||||
@ -482,10 +517,10 @@ writeln(defaultsProc(x=11));
|
||||
writeln(defaultsProc(x=12, y=5.432));
|
||||
writeln(defaultsProc(y=9.876, x=13));
|
||||
|
||||
// The ? operator is called the query operator, and is used to take
|
||||
// The ``?`` operator is called the query operator, and is used to take
|
||||
// undetermined values like tuple or array sizes and generic types.
|
||||
// For example, taking arrays as parameters. The query operator is used to
|
||||
// determine the domain of A. This is uesful for defining the return type,
|
||||
// determine the domain of ``A``. This is useful for defining the return type,
|
||||
// though it's not required.
|
||||
proc invertArray(A: [?D] int): [D] int{
|
||||
for a in A do a = -a;
|
||||
@ -509,7 +544,7 @@ genericProc(1, 2);
|
||||
genericProc(1.2, 2.3);
|
||||
genericProc(1.0+2.0i, 3.0+4.0i);
|
||||
|
||||
// We can also enforce a form of polymorphism with the where clause
|
||||
// We can also enforce a form of polymorphism with the ``where`` clause
|
||||
// This allows the compiler to decide which function to use.
|
||||
// Note: That means that all information needs to be known at compile-time.
|
||||
// The param modifier on the arg is used to enforce this constraint.
|
||||
@ -526,13 +561,13 @@ proc whereProc(param N : int): void
|
||||
whereProc(10);
|
||||
whereProc(-1);
|
||||
|
||||
// whereProc(0) would result in a compiler error because there
|
||||
// are no functions that satisfy the where clause's condition.
|
||||
// We could have defined a whereProc without a where clause
|
||||
// ``whereProc(0)`` would result in a compiler error because there
|
||||
// are no functions that satisfy the ``where`` clause's condition.
|
||||
// We could have defined a ``whereProc`` without a ``where`` clause
|
||||
// that would then have served as a catch all for all the other cases
|
||||
// (of which there is only one).
|
||||
|
||||
// where clauses can also be used to constrain based on argument type.
|
||||
// ``where`` clauses can also be used to constrain based on argument type.
|
||||
proc whereType(x: ?t) where t == int {
|
||||
writeln("Inside 'int' version of 'whereType': ", x);
|
||||
}
|
||||
@ -544,7 +579,9 @@ proc whereType(x: ?t) {
|
||||
whereType(42);
|
||||
whereType("hello");
|
||||
|
||||
// Intents
|
||||
/*
|
||||
Intents
|
||||
*/
|
||||
|
||||
/* Intent modifiers on the arguments convey how those arguments are passed to the procedure.
|
||||
|
||||
@ -571,7 +608,7 @@ intentsProc(inVar, outVar, inoutVar, refVar);
|
||||
writeln("Outside After: ", (inVar, outVar, inoutVar, refVar));
|
||||
|
||||
// Similarly, we can define intents on the return type.
|
||||
// refElement returns a reference to an element of array.
|
||||
// ``refElement`` returns a reference to an element of array.
|
||||
// This makes more practical sense for class methods where references to
|
||||
// elements in a data-structure are returned via a method or iterator.
|
||||
proc refElement(array : [?D] ?T, idx) ref : T {
|
||||
@ -586,14 +623,16 @@ refToElem = -2; // modify reference which modifies actual value in array
|
||||
writeln(refToElem);
|
||||
writeln(myChangingArray);
|
||||
|
||||
// Operator Definitions
|
||||
/*
|
||||
Operator Definitions
|
||||
*/
|
||||
|
||||
// Chapel allows for operators to be overloaded.
|
||||
// We can define the unary operators:
|
||||
// + - ! ~
|
||||
// ``+ - ! ~``
|
||||
// and the binary operators:
|
||||
// + - * / % ** == <= >= < > << >> & | ˆ by
|
||||
// += -= *= /= %= **= &= |= ˆ= <<= >>= <=>
|
||||
// ``+ - * / % ** == <= >= < > << >> & | ˆ by``
|
||||
// ``+= -= *= /= %= **= &= |= ˆ= <<= >>= <=>``
|
||||
|
||||
// Boolean exclusive or operator.
|
||||
proc ^(left : bool, right : bool): bool {
|
||||
@ -605,25 +644,28 @@ writeln(false ^ true);
|
||||
writeln(true ^ false);
|
||||
writeln(false ^ false);
|
||||
|
||||
// Define a * operator on any two types that returns a tuple of those types.
|
||||
// Define a ``*`` operator on any two types that returns a tuple of those types.
|
||||
proc *(left : ?ltype, right : ?rtype): (ltype, rtype) {
|
||||
writeln("\tIn our '*' overload!");
|
||||
return (left, right);
|
||||
}
|
||||
|
||||
writeln(1 * "a"); // Uses our * operator.
|
||||
writeln(1 * 2); // Uses the default * operator.
|
||||
writeln(1 * "a"); // Uses our ``*`` operator.
|
||||
writeln(1 * 2); // Uses the default ``*`` operator.
|
||||
|
||||
// Note: You could break everything if you get careless with your overloads.
|
||||
// This here will break everything. Don't do it.
|
||||
|
||||
/*
|
||||
proc +(left: int, right: int): int {
|
||||
return left - right;
|
||||
}
|
||||
/*
|
||||
|
||||
proc +(left: int, right: int): int {
|
||||
return left - right;
|
||||
}
|
||||
*/
|
||||
|
||||
// Iterators
|
||||
/*
|
||||
Iterators
|
||||
*/
|
||||
|
||||
// Iterators are sisters to the procedure, and almost everything about
|
||||
// procedures also applies to iterators. However, instead of returning a single
|
||||
@ -656,7 +698,7 @@ for i in absolutelyNothing(10) {
|
||||
}
|
||||
|
||||
// We can zipper together two or more iterators (who have the same number
|
||||
// of iterations) using zip() to create a single zipped iterator, where each
|
||||
// of iterations) using ``zip()`` to create a single zipped iterator, where each
|
||||
// iteration of the zipped iterator yields a tuple of one value yielded
|
||||
// from each iterator.
|
||||
for (positive, negative) in zip(1..5, -5..-1) do
|
||||
@ -683,11 +725,10 @@ for (i, j) in zip(toThisArray.domain, -100..#5) {
|
||||
}
|
||||
writeln(toThisArray);
|
||||
|
||||
// This is very important in understanding why this statement exhibits a
|
||||
// runtime error.
|
||||
// This is very important in understanding why this statement exhibits a runtime error.
|
||||
|
||||
/*
|
||||
var iterArray : [1..10] int = [i in 1..10] if (i % 2 == 1) then i;
|
||||
/*
|
||||
var iterArray : [1..10] int = [i in 1..10] if (i % 2 == 1) then i;
|
||||
*/
|
||||
|
||||
// Even though the domain of the array and the loop-expression are
|
||||
@ -695,8 +736,9 @@ writeln(toThisArray);
|
||||
// Because iterators can yield nothing, that iterator yields a different number
|
||||
// of things than the domain of the array or loop, which is not allowed.
|
||||
|
||||
// Classes
|
||||
|
||||
/*
|
||||
Classes
|
||||
*/
|
||||
// Classes are similar to those in C++ and Java, allocated on the heap.
|
||||
class MyClass {
|
||||
|
||||
@ -704,13 +746,16 @@ class MyClass {
|
||||
var memberInt : int;
|
||||
var memberBool : bool = true;
|
||||
|
||||
// Explicitly defined initializer.
|
||||
// We also get the compiler-generated initializer, with one argument per field.
|
||||
// Note that soon there will be no compiler-generated initializer when we
|
||||
// define any initializer(s) explicitly.
|
||||
proc init(val : real) {
|
||||
this.memberInt = ceil(val): int;
|
||||
}
|
||||
// By default, any class that doesn't define an initializer gets a
|
||||
// compiler-generated initializer, with one argument per field and
|
||||
// the field's initial value as the argument's default value.
|
||||
// Alternatively, the user can define initializers manually as shown
|
||||
// in the following commented-out routine:
|
||||
//
|
||||
/* // proc init(val : real) {
|
||||
// this.memberInt = ceil(val): int;
|
||||
// }
|
||||
*/
|
||||
|
||||
// Explicitly defined deinitializer.
|
||||
// If we did not write one, we would get the compiler-generated deinitializer,
|
||||
@ -738,37 +783,45 @@ class MyClass {
|
||||
} // end MyClass
|
||||
|
||||
// Call compiler-generated initializer, using default value for memberBool.
|
||||
var myObject = new MyClass(10);
|
||||
myObject = new MyClass(memberInt = 10); // Equivalent
|
||||
writeln(myObject.getMemberInt());
|
||||
{
|
||||
var myObject = new owned MyClass(10);
|
||||
myObject = new owned MyClass(memberInt = 10); // Equivalent
|
||||
writeln(myObject.getMemberInt());
|
||||
|
||||
// Same, but provide a memberBool value explicitly.
|
||||
var myDiffObject = new MyClass(-1, true);
|
||||
myDiffObject = new MyClass(memberInt = -1,
|
||||
memberBool = true); // Equivalent
|
||||
writeln(myDiffObject);
|
||||
// Same, but provide a memberBool value explicitly.
|
||||
var myDiffObject = new owned MyClass(-1, true);
|
||||
myDiffObject = new owned MyClass(memberInt = -1,
|
||||
memberBool = true); // Equivalent
|
||||
writeln(myDiffObject);
|
||||
|
||||
// Call the initializer we wrote.
|
||||
var myOtherObject = new MyClass(1.95);
|
||||
myOtherObject = new MyClass(val = 1.95); // Equivalent
|
||||
writeln(myOtherObject.getMemberInt());
|
||||
// Similar, but rely on the default value of memberInt, passing in memberBool.
|
||||
var myThirdObject = new owned MyClass(memberBool = true);
|
||||
writeln(myThirdObject);
|
||||
|
||||
// We can define an operator on our class as well, but
|
||||
// the definition has to be outside the class definition.
|
||||
proc +(A : MyClass, B : MyClass) : MyClass {
|
||||
return new MyClass(memberInt = A.getMemberInt() + B.getMemberInt(),
|
||||
memberBool = A.getMemberBool() || B.getMemberBool());
|
||||
// If the user-defined initializer above had been uncommented, we could
|
||||
// make the following calls:
|
||||
//
|
||||
/* // var myOtherObject = new MyClass(1.95);
|
||||
// myOtherObject = new MyClass(val = 1.95);
|
||||
// writeln(myOtherObject.getMemberInt());
|
||||
*/
|
||||
|
||||
// We can define an operator on our class as well, but
|
||||
// the definition has to be outside the class definition.
|
||||
proc +(A : MyClass, B : MyClass) : owned MyClass {
|
||||
return
|
||||
new owned MyClass(memberInt = A.getMemberInt() + B.getMemberInt(),
|
||||
memberBool = A.getMemberBool() || B.getMemberBool());
|
||||
}
|
||||
|
||||
var plusObject = myObject + myDiffObject;
|
||||
writeln(plusObject);
|
||||
|
||||
// Destruction of an object: calls the deinit() routine and frees its memory.
|
||||
// ``unmanaged`` variables should have ``delete`` called on them.
|
||||
// ``owned`` variables are destroyed when they go out of scope.
|
||||
}
|
||||
|
||||
var plusObject = myObject + myDiffObject;
|
||||
writeln(plusObject);
|
||||
|
||||
// Destruction.
|
||||
delete myObject;
|
||||
delete myDiffObject;
|
||||
delete myOtherObject;
|
||||
delete plusObject;
|
||||
|
||||
// Classes can inherit from one or more parent classes
|
||||
class MyChildClass : MyClass {
|
||||
var memberComplex: complex;
|
||||
@ -780,42 +833,46 @@ class GenericClass {
|
||||
var classDomain: domain(1);
|
||||
var classArray: [classDomain] classType;
|
||||
|
||||
// Explicit constructor.
|
||||
proc GenericClass(type classType, elements : int) {
|
||||
this.classDomain = {1..#elements};
|
||||
// Explicit initializer.
|
||||
proc init(type classType, elements : int) {
|
||||
this.classType = classType;
|
||||
this.classDomain = {1..elements};
|
||||
// all generic and const fields must be initialized in "phase 1" prior
|
||||
// to a call to the superclass initializer.
|
||||
}
|
||||
|
||||
// Copy constructor.
|
||||
// Note: We still have to put the type as an argument, but we can
|
||||
// default to the type of the other object using the query (?) operator.
|
||||
// Further, we can take advantage of this to allow our copy constructor
|
||||
// to copy classes of different types and cast on the fly.
|
||||
proc GenericClass(other : GenericClass(?otherType),
|
||||
type classType = otherType) {
|
||||
// Copy-style initializer.
|
||||
// Note: We include a type argument whose default is the type of the first
|
||||
// argument. This lets our initializer copy classes of different
|
||||
// types and cast on the fly.
|
||||
proc init(other : GenericClass(?),
|
||||
type classType = other.classType) {
|
||||
this.classType = classType;
|
||||
this.classDomain = other.classDomain;
|
||||
// Copy and cast
|
||||
for idx in this.classDomain do this[idx] = other[idx] : classType;
|
||||
this.classArray = for o in other do o: classType; // copy and cast
|
||||
}
|
||||
|
||||
// Define bracket notation on a GenericClass
|
||||
// object so it can behave like a normal array
|
||||
// i.e. objVar[i] or objVar(i)
|
||||
// i.e. ``objVar[i]`` or ``objVar(i)``
|
||||
proc this(i : int) ref : classType {
|
||||
return this.classArray[i];
|
||||
}
|
||||
|
||||
// Define an implicit iterator for the class
|
||||
// to yield values from the array to a loop
|
||||
// i.e. for i in objVar do ...
|
||||
// i.e. ``for i in objVar do ...``
|
||||
iter these() ref : classType {
|
||||
for i in this.classDomain do
|
||||
yield this[i];
|
||||
}
|
||||
} // end GenericClass
|
||||
|
||||
// Allocate an owned instance of our class
|
||||
var realList = new owned GenericClass(real, 10);
|
||||
|
||||
// We can assign to the member array of the object using the bracket
|
||||
// notation that we defined.
|
||||
var realList = new GenericClass(real, 10);
|
||||
for i in realList.classDomain do realList[i] = i + 1.0;
|
||||
|
||||
// We can iterate over the values in our list with the iterator
|
||||
@ -823,23 +880,25 @@ for i in realList.classDomain do realList[i] = i + 1.0;
|
||||
for value in realList do write(value, ", ");
|
||||
writeln();
|
||||
|
||||
// Make a copy of realList using the copy constructor.
|
||||
var copyList = new GenericClass(realList);
|
||||
// Make a copy of realList using the copy initializer.
|
||||
var copyList = new owned GenericClass(realList);
|
||||
for value in copyList do write(value, ", ");
|
||||
writeln();
|
||||
|
||||
// Make a copy of realList and change the type, also using the copy constructor.
|
||||
var copyNewTypeList = new GenericClass(realList, int);
|
||||
// Make a copy of realList and change the type, also using the copy initializer.
|
||||
var copyNewTypeList = new owned GenericClass(realList, int);
|
||||
for value in copyNewTypeList do write(value, ", ");
|
||||
writeln();
|
||||
|
||||
|
||||
// Modules
|
||||
/*
|
||||
Modules
|
||||
*/
|
||||
|
||||
// Modules are Chapel's way of managing name spaces.
|
||||
// The files containing these modules do not need to be named after the modules
|
||||
// (as in Java), but files implicitly name modules.
|
||||
// For example, this file implicitly names the learnChapelInYMinutes module
|
||||
// For example, this file implicitly names the ``learnChapelInYMinutes`` module
|
||||
|
||||
module OurModule {
|
||||
|
||||
@ -870,21 +929,23 @@ module OurModule {
|
||||
}
|
||||
} // end OurModule
|
||||
|
||||
// Using OurModule also uses all the modules it uses.
|
||||
// Since OurModule uses Time, we also use Time.
|
||||
// Using ``OurModule`` also uses all the modules it uses.
|
||||
// Since ``OurModule`` uses ``Time``, we also use ``Time``.
|
||||
use OurModule;
|
||||
|
||||
// At this point we have not used ChildModule or SiblingModule so
|
||||
// their symbols (i.e. foo) are not available to us. However, the module
|
||||
// names are available, and we can explicitly call foo() through them.
|
||||
// At this point we have not used ``ChildModule`` or ``SiblingModule`` so
|
||||
// their symbols (i.e. ``foo``) are not available to us. However, the module
|
||||
// names are available, and we can explicitly call ``foo()`` through them.
|
||||
SiblingModule.foo();
|
||||
OurModule.ChildModule.foo();
|
||||
|
||||
// Now we use ChildModule, enabling unqualified calls.
|
||||
// Now we use ``ChildModule``, enabling unqualified calls.
|
||||
use ChildModule;
|
||||
foo();
|
||||
|
||||
// Parallelism
|
||||
/*
|
||||
Parallelism
|
||||
*/
|
||||
|
||||
// In other languages, parallelism is typically done with
|
||||
// complicated libraries and strange class structure hierarchies.
|
||||
@ -894,9 +955,9 @@ foo();
|
||||
// executed.
|
||||
proc main() {
|
||||
|
||||
// A begin statement will spin the body of that statement off
|
||||
// A ``begin`` statement will spin the body of that statement off
|
||||
// into one new task.
|
||||
// A sync statement will ensure that the progress of the main
|
||||
// A ``sync`` statement will ensure that the progress of the main
|
||||
// task will not progress until the children have synced back up.
|
||||
|
||||
sync {
|
||||
@ -913,7 +974,7 @@ proc main() {
|
||||
writeln("fibonacci(",n,") = ", fibonacci(n));
|
||||
}
|
||||
|
||||
// A cobegin statement will spin each statement of the body into one new
|
||||
// A ``cobegin`` statement will spin each statement of the body into one new
|
||||
// task. Notice here that the prints from each statement may happen in any
|
||||
// order.
|
||||
cobegin {
|
||||
@ -929,17 +990,17 @@ proc main() {
|
||||
}
|
||||
}
|
||||
|
||||
// A coforall loop will create a new task for EACH iteration.
|
||||
// A ``coforall`` loop will create a new task for EACH iteration.
|
||||
// Again we see that prints happen in any order.
|
||||
// NOTE: coforall should be used only for creating tasks!
|
||||
// NOTE: ``coforall`` should be used only for creating tasks!
|
||||
// Using it to iterating over a structure is very a bad idea!
|
||||
var num_tasks = 10; // Number of tasks we want
|
||||
coforall taskID in 1..#num_tasks {
|
||||
coforall taskID in 1..num_tasks {
|
||||
writeln("Hello from task# ", taskID);
|
||||
}
|
||||
|
||||
// forall loops are another parallel loop, but only create a smaller number
|
||||
// of tasks, specifically --dataParTasksPerLocale= number of tasks.
|
||||
// ``forall`` loops are another parallel loop, but only create a smaller number
|
||||
// of tasks, specifically ``--dataParTasksPerLocale=`` number of tasks.
|
||||
forall i in 1..100 {
|
||||
write(i, ", ");
|
||||
}
|
||||
@ -951,10 +1012,10 @@ proc main() {
|
||||
// (1..3, 4..6, or 7..9) doing that chunk serially, but each task happens
|
||||
// in parallel. Your results may depend on your machine and configuration
|
||||
|
||||
// For both the forall and coforall loops, the execution of the
|
||||
// For both the ``forall`` and ``coforall`` loops, the execution of the
|
||||
// parent task will not continue until all the children sync up.
|
||||
|
||||
// forall loops are particularly useful for parallel iteration over arrays.
|
||||
// ``forall`` loops are particularly useful for parallel iteration over arrays.
|
||||
// Lets run an experiment to see how much faster a parallel loop is
|
||||
use Time; // Import the Time module to use Timer objects
|
||||
var timer: Timer;
|
||||
@ -982,14 +1043,14 @@ proc main() {
|
||||
// the parallel loop went faster than the serial loop.
|
||||
|
||||
// The bracket style loop-expression described
|
||||
// much earlier implicitly uses a forall loop.
|
||||
// much earlier implicitly uses a ``forall`` loop.
|
||||
[val in myBigArray] val = 1 / val; // Parallel operation
|
||||
|
||||
// Atomic variables, common to many languages, are ones whose operations
|
||||
// occur uninterrupted. Multiple threads can therefore modify atomic
|
||||
// variables and can know that their values are safe.
|
||||
// Chapel atomic variables can be of type bool, int,
|
||||
// uint, and real.
|
||||
// Chapel atomic variables can be of type ``bool``, ``int``,
|
||||
// ``uint``, and ``real``.
|
||||
var uranium: atomic int;
|
||||
uranium.write(238); // atomically write a variable
|
||||
writeln(uranium.read()); // atomically read a variable
|
||||
@ -1003,7 +1064,7 @@ proc main() {
|
||||
writeln("uranium was ", was, " but is now ", replaceWith);
|
||||
|
||||
var isEqualTo = 235;
|
||||
if uranium.compareExchange(isEqualTo, replaceWith) {
|
||||
if uranium.compareAndSwap(isEqualTo, replaceWith) {
|
||||
writeln("uranium was equal to ", isEqualTo,
|
||||
" so replaced value with ", replaceWith);
|
||||
} else {
|
||||
@ -1025,7 +1086,7 @@ proc main() {
|
||||
}
|
||||
}
|
||||
|
||||
// sync variables have two states: empty and full.
|
||||
// ``sync`` variables have two states: empty and full.
|
||||
// If you read an empty variable or write a full variable, you are waited
|
||||
// until the variable is full or empty again.
|
||||
var someSyncVar$: sync int; // varName$ is a convention not a law.
|
||||
@ -1043,9 +1104,8 @@ proc main() {
|
||||
}
|
||||
}
|
||||
|
||||
// single vars can only be written once. A read on an unwritten single
|
||||
// results in a wait, but when the variable has a value it can be read
|
||||
// indefinitely.
|
||||
// ``single`` vars can only be written once. A read on an unwritten ``single``
|
||||
// results in a wait, but when the variable has a value it can be read indefinitely.
|
||||
var someSingleVar$: single int; // varName$ is a convention not a law.
|
||||
sync {
|
||||
begin { // Reader task
|
||||
@ -1063,7 +1123,7 @@ proc main() {
|
||||
}
|
||||
}
|
||||
|
||||
// Here's an example using atomics and a sync variable to create a
|
||||
// Here's an example using atomics and a ``sync`` variable to create a
|
||||
// count-down mutex (also known as a multiplexer).
|
||||
var count: atomic int; // our counter
|
||||
var lock$: sync bool; // the mutex lock
|
||||
@ -1074,7 +1134,7 @@ proc main() {
|
||||
// (full:unlocked / empty:locked)
|
||||
// Also, writeXF() fills (F) the sync var regardless of its state (X)
|
||||
|
||||
coforall task in 1..#5 { // Generate tasks
|
||||
coforall task in 1..5 { // Generate tasks
|
||||
// Create a barrier
|
||||
do {
|
||||
lock$; // Read lock$ (wait)
|
||||
@ -1091,7 +1151,7 @@ proc main() {
|
||||
lock$.writeXF(true); // Set lock$ to full (signal)
|
||||
}
|
||||
|
||||
// We can define the operations + * & | ^ && || min max minloc maxloc
|
||||
// We can define the operations ``+ * & | ^ && || min max minloc maxloc``
|
||||
// over an entire array using scans and reductions.
|
||||
// Reductions apply the operation over the entire array and
|
||||
// result in a scalar value.
|
||||
@ -1099,7 +1159,7 @@ proc main() {
|
||||
var sumOfValues = + reduce listOfValues;
|
||||
var maxValue = max reduce listOfValues; // 'max' give just max value
|
||||
|
||||
// maxloc gives max value and index of the max value.
|
||||
// ``maxloc`` gives max value and index of the max value.
|
||||
// Note: We have to zip the array and domain together with the zip iterator.
|
||||
var (theMaxValue, idxOfMax) = maxloc reduce zip(listOfValues,
|
||||
listOfValues.domain);
|
||||
@ -1108,7 +1168,7 @@ proc main() {
|
||||
|
||||
// Scans apply the operation incrementally and return an array with the
|
||||
// values of the operation at that index as it progressed through the
|
||||
// array from array.domain.low to array.domain.high.
|
||||
// array from ``array.domain.low`` to ``array.domain.high``.
|
||||
var runningSumOfValues = + scan listOfValues;
|
||||
var maxScan = max scan listOfValues;
|
||||
writeln(runningSumOfValues);
|
||||
@ -1116,8 +1176,7 @@ proc main() {
|
||||
} // end main()
|
||||
```
|
||||
|
||||
Who is this tutorial for?
|
||||
-------------------------
|
||||
## Who is this tutorial for?
|
||||
|
||||
This tutorial is for people who want to learn the ropes of chapel without
|
||||
having to hear about what fiber mixture the ropes are, or how they were
|
||||
@ -1132,28 +1191,27 @@ to see if more topics have been added or more tutorials created.
|
||||
|
||||
### What this tutorial is lacking:
|
||||
|
||||
* Exposition of the [standard modules](https://chapel-lang.org/docs/latest/modules/standard.html)
|
||||
* Multiple Locales (distributed memory system)
|
||||
* Records
|
||||
* Parallel iterators
|
||||
* Exposition of the [standard modules](https://chapel-lang.org/docs/latest/modules/standard.html)
|
||||
* Multiple Locales (distributed memory system)
|
||||
* Records
|
||||
* Parallel iterators
|
||||
|
||||
Your input, questions, and discoveries are important to the developers!
|
||||
-----------------------------------------------------------------------
|
||||
## Your input, questions, and discoveries are important to the developers!
|
||||
|
||||
The Chapel language is still in active development, so there are
|
||||
occasional hiccups with performance and language features. The more information
|
||||
you give the Chapel development team about issues you encounter or features you
|
||||
would like to see, the better the language becomes.
|
||||
There are several ways to interact with the developers:
|
||||
+ [Gitter chat](https://gitter.im/chapel-lang/chapel)
|
||||
+ [sourceforge email lists](https://sourceforge.net/p/chapel/mailman)
|
||||
|
||||
* [Gitter chat](https://gitter.im/chapel-lang/chapel)
|
||||
* [sourceforge email lists](https://sourceforge.net/p/chapel/mailman)
|
||||
|
||||
If you're really interested in the development of the compiler or contributing
|
||||
to the project, [check out the master GitHub repository](https://github.com/chapel-lang/chapel).
|
||||
It is under the [Apache 2.0 License](http://www.apache.org/licenses/LICENSE-2.0).
|
||||
|
||||
Installing the Compiler
|
||||
-----------------------
|
||||
## Installing the Compiler
|
||||
|
||||
[The Official Chapel documentation details how to download and compile the Chapel compiler.](https://chapel-lang.org/docs/usingchapel/QUICKSTART.html)
|
||||
|
||||
@ -1161,23 +1219,22 @@ Chapel can be built and installed on your average 'nix machine (and cygwin).
|
||||
[Download the latest release version](https://github.com/chapel-lang/chapel/releases/)
|
||||
and it's as easy as
|
||||
|
||||
1. `tar -xvf chapel-<VERSION>.tar.gz`
|
||||
2. `cd chapel-<VERSION>`
|
||||
3. `source util/setchplenv.bash # or .sh or .csh or .fish`
|
||||
4. `make`
|
||||
5. `make check # optional`
|
||||
1. `tar -xvf chapel-<VERSION>.tar.gz`
|
||||
2. `cd chapel-<VERSION>`
|
||||
3. `source util/setchplenv.bash # or .sh or .csh or .fish`
|
||||
4. `make`
|
||||
5. `make check # optional`
|
||||
|
||||
You will need to `source util/setchplenv.EXT` from within the Chapel directory
|
||||
(`$CHPL_HOME`) every time your terminal starts so it's suggested that you drop
|
||||
that command in a script that will get executed on startup (like .bashrc).
|
||||
|
||||
Chapel is easily installed with Brew for macOS
|
||||
Chapel is easily installed on macOS with Homebrew
|
||||
|
||||
1. `brew update`
|
||||
2. `brew install chapel`
|
||||
1. `brew update`
|
||||
2. `brew install chapel`
|
||||
|
||||
Compiling Code
|
||||
--------------
|
||||
## Compiling Code
|
||||
|
||||
Builds like other compilers:
|
||||
|
||||
@ -1185,10 +1242,10 @@ Builds like other compilers:
|
||||
|
||||
Notable arguments:
|
||||
|
||||
* `--fast`: enables a number of optimizations and disables array bounds
|
||||
checks. Should only enable when application is stable.
|
||||
* `--set <Symbol Name>=<Value>`: set config param `<Symbol Name>` to `<Value>`
|
||||
at compile-time.
|
||||
* `--main-module <Module Name>`: use the main() procedure found in the module
|
||||
`<Module Name>` as the executable's main.
|
||||
* `--module-dir <Directory>`: includes `<Directory>` in the module search path.
|
||||
* `--fast`: enables a number of optimizations and disables array bounds
|
||||
checks. Should only enable when application is stable.
|
||||
* `--set <Symbol Name>=<Value>`: set config param `<Symbol Name>` to `<Value>`
|
||||
at compile-time.
|
||||
* `--main-module <Module Name>`: use the main() procedure found in the module
|
||||
`<Module Name>` as the executable's main.
|
||||
* `--module-dir <Directory>`: includes `<Directory>` in the module search path.
|
||||
|
@ -504,8 +504,8 @@ sqr ;; => #<procedure (sqr x)>
|
||||
|
||||
(import star-squarer)
|
||||
(square 3) ;; => ((* * *)(* * *)(* * *))
|
||||
|
||||
```
|
||||
|
||||
## Further Reading
|
||||
* [CHICKEN User's Manual](https://wiki.call-cc.org/manual).
|
||||
* [R5RS standards](http://www.schemers.org/Documents/Standards/R5RS)
|
@ -184,12 +184,6 @@ organizations.
|
||||
*and then re-run the program. This time the output is:
|
||||
|
||||
THE FULL NAME IS: BOB GIBBERISH COBB
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
```
|
||||
|
||||
##Ready For More?
|
||||
|
@ -233,6 +233,7 @@ ColdFusion started as a tag-based language. Almost all functionality is availabl
|
||||
|
||||
<em>Code for reference (Functions must return something to support IE)</em>
|
||||
```
|
||||
|
||||
```cfs
|
||||
<cfcomponent>
|
||||
<cfset this.hello = "Hello" />
|
||||
|
@ -17,7 +17,6 @@ popular and recent book is [Land of Lisp](http://landoflisp.com/). A new book ab
|
||||
|
||||
|
||||
```lisp
|
||||
|
||||
;;;-----------------------------------------------------------------------------
|
||||
;;; 0. Syntax
|
||||
;;;-----------------------------------------------------------------------------
|
||||
|
@ -9,7 +9,6 @@ contributors:
|
||||
---
|
||||
|
||||
```crystal
|
||||
|
||||
# This is a comment
|
||||
|
||||
# Everything is an object
|
||||
@ -556,7 +555,6 @@ rescue ex4 # catch any kind of exception
|
||||
end
|
||||
|
||||
ex #=> "ex2"
|
||||
|
||||
```
|
||||
|
||||
## Additional resources
|
||||
|
@ -1,5 +1,5 @@
|
||||
---
|
||||
language: brainfuck
|
||||
language: bf
|
||||
contributors:
|
||||
- ["Prajit Ramachandran", "http://prajitr.github.io/"]
|
||||
- ["Mathias Bynens", "http://mathiasbynens.be/"]
|
@ -220,9 +220,11 @@ p { vlastnost: hodnota !important; }
|
||||
```
|
||||
|
||||
a tento element
|
||||
|
||||
```xml
|
||||
<p style='/*F*/ vlastnost:hodnota;' trida='trida1 trida2' attr='hodnota' />
|
||||
```
|
||||
|
||||
Priorita stylu je následující. Pamatujte, priorita pro každou **vlastnost**, ne pro celý blok.
|
||||
|
||||
* `E` má nejvyšší prioritu kvůli slůvku `!important`. Je doporučováno se úplně vyhnout jeho použití.
|
||||
|
@ -90,7 +90,7 @@ může obsahovat nové řádky` // Opět typ řetězec.
|
||||
// Můžeme použít ne ASCII znaky, Go používá UTF-8.
|
||||
g := 'Σ' // type runa, což je alias na int32 a ukládá se do něj znak UTF-8
|
||||
|
||||
f := 3.14195 // float64, je IEEE-754 64-bit číslem s plovoucí čárkou.
|
||||
f := 3.14159 // float64, je IEEE-754 64-bit číslem s plovoucí čárkou.
|
||||
c := 3 + 4i // complex128, interně uložené jako dva float64.
|
||||
|
||||
// takhle vypadá var s inicializací
|
||||
@ -408,24 +408,24 @@ func requestServer() {
|
||||
|
||||
## Kam dále
|
||||
|
||||
Vše hlavní o Go se nachází na [oficiálních stránkách go](http://golang.org/).
|
||||
Vše hlavní o Go se nachází na [oficiálních stránkách go](https://go.dev/).
|
||||
Tam najdete tutoriály, interaktivní konzolu a mnoho materiálu ke čtení.
|
||||
Kromě úvodu, [dokumenty](https://golang.org/doc/) tam obsahují jak psát čistý kód v Go
|
||||
Kromě úvodu, [dokumenty](https://go.dev/doc/) tam obsahují jak psát čistý kód v Go
|
||||
popis balíčků (package), dokumentaci příkazové řádky a historii releasů.
|
||||
|
||||
Také doporučujeme přečíst si definici jazyka. Je čtivá a překvapivě krátká. Tedy alespoň proti
|
||||
jiným současným jazyků.
|
||||
|
||||
Pokud si chcete pohrát s Go, tak navštivte [hřiště Go](https://play.golang.org/p/r46YvCu-XX).
|
||||
Můžete tam spouštět programy s prohlížeče. Také můžete [https://play.golang.org](https://play.golang.org) použít jako
|
||||
Pokud si chcete pohrát s Go, tak navštivte [hřiště Go](https://go.dev/play/p/r46YvCu-XX).
|
||||
Můžete tam spouštět programy s prohlížeče. Také můžete [https://go.dev/play/](https://go.dev/play/) použít jako
|
||||
[REPL](https://en.wikipedia.org/wiki/Read-eval-print_loop), kde si v rychlosti vyzkoušíte věci, bez instalace Go.
|
||||
|
||||
Na vašem knižním seznamu, by neměly chybět [zdrojáky stadardní knihovny](http://golang.org/src/pkg/).
|
||||
Důkladně popisuje a dokumentuje Go, styl zápisu Go a Go idiomy. Pokud kliknete na [dokumentaci](http://golang.org/pkg/)
|
||||
Na vašem knižním seznamu, by neměly chybět [zdrojáky stadardní knihovny](https://go.dev/src/).
|
||||
Důkladně popisuje a dokumentuje Go, styl zápisu Go a Go idiomy. Pokud kliknete na [dokumentaci](https://go.dev/pkg/)
|
||||
tak se podíváte na dokumentaci.
|
||||
|
||||
Dalším dobrým zdrojem informací je [Go v ukázkách](https://gobyexample.com/).
|
||||
|
||||
Go mobile přidává podporu pro Android a iOS. Můžete s ním psát nativní mobilní aplikace nebo knihovny, které půjdou
|
||||
spustit přes Javu (pro Android), nebo Objective-C (pro iOS). Navštivte [web Go Mobile](https://github.com/golang/go/wiki/Mobile)
|
||||
spustit přes Javu (pro Android), nebo Objective-C (pro iOS). Navštivte [web Go Mobile](https://go.dev/wiki/Mobile)
|
||||
pro více informací.
|
||||
|
@ -295,7 +295,6 @@ class Samuel
|
||||
|
||||
$cat = new Samuel();
|
||||
$cat instanceof KittenInterface === true; // True
|
||||
|
||||
```
|
||||
|
||||
## Více informací
|
||||
|
@ -620,7 +620,7 @@ na stránkách Mozilla Developer Network.
|
||||
[2]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
|
||||
[3]: https://developer.mozilla.org/en-US/docs/Using_the_W3C_DOM_Level_1_Core
|
||||
[4]: http://www.learneroo.com/modules/64/nodes/350
|
||||
[5]: http://bonsaiden.github.io/JavaScript-Garden/
|
||||
[5]: https://shamansir.github.io/JavaScript-Garden/
|
||||
[6]: http://www.amazon.com/gp/product/0596805527/
|
||||
[7]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript
|
||||
[8]: http://eloquentjavascript.net/
|
||||
|
@ -19,41 +19,18 @@ které markdown dále zpracovávají) mírně odlišuje. V této příručce se
|
||||
upozorňovat, kdy se jedná o obecnou vlastnost markdownu a kdy se jedná o
|
||||
specifickou vlastnost daného parseru.
|
||||
|
||||
## Obsah
|
||||
|
||||
- [Obsah](#obsah)
|
||||
- [HTML Elementy](#html-elementy)
|
||||
- [Nadpisy](#nadpisy)
|
||||
- [Jednoduché stylování textu](#jednoduché-stylování-textu)
|
||||
- [Odstavce](#odstavce)
|
||||
- [Blokové citace](#blokové-citace)
|
||||
- [Seznamy](#seznamy)
|
||||
- [Bloky kódu](#bloky-kódu)
|
||||
- [Vodorovná čára (`<hr />`)](#vodorovná-čára-hr-)
|
||||
- [Odkazy](#odkazy)
|
||||
- [Obsahy](#obsahy)
|
||||
- [Obrázky](#obrázky)
|
||||
- [Ostatní](#ostatní)
|
||||
- [Automatické odkazy](#automatické-odkazy)
|
||||
- [Automatické odkazy z emailů](#automatické-odkazy-z-emailů)
|
||||
- [Escapování znaků](#escapování-znaků)
|
||||
- [Klávesové zkratky](#klávesové-zkratky)
|
||||
- [Tabulky](#tabulky)
|
||||
- [Markdownlint](#markdownlint)
|
||||
- [Reference](#reference)
|
||||
|
||||
## HTML Elementy
|
||||
|
||||
Markdown je nadstavba HTML. To znamená, že každý HTML kód je zároveň validním
|
||||
kódem v Markdownu.
|
||||
|
||||
```md
|
||||
<!-- To znamená, že v Markdownu můžeme používat HTML elementy jako například
|
||||
komentáře, které nebudou ovlivněny parserem Markdownu. Na druhou stranu to také
|
||||
znamená, že pokud ve svém Markdown kódu vytvoříte HTML element, už v rámci
|
||||
tohoto elementu nelze použít Markdown.
|
||||
<!-- To znamená, že v Markdownu můžeme používat HTML elementy jako například
|
||||
komentáře, které nebudou ovlivněny parserem Markdownu. Na druhou stranu to také
|
||||
znamená, že pokud ve svém Markdown kódu vytvoříte HTML element, už v rámci
|
||||
tohoto elementu nelze použít Markdown.
|
||||
|
||||
Markdown využívá i tato stránka, a tak by tento text, kdyby nebyl obalen v bloku
|
||||
Markdown využívá i tato stránka, a tak by tento text, kdyby nebyl obalen v bloku
|
||||
kódu (viz níže), jako validní HTML komentář vůbec nebyl vidět. -->
|
||||
```
|
||||
|
||||
@ -132,7 +109,7 @@ Blokové citace se dělají jednoduše uvozením řádku znakem >.
|
||||
|
||||
```md
|
||||
> Toto je bloková citace. Můžete dokonce
|
||||
> manuálně rozdělit řádky, a před každý vložit >, nebo nechat vaše řádky
|
||||
> manuálně rozdělit řádky, a před každý vložit >, nebo nechat vaše řádky
|
||||
> jakkoli dlouhé, ať se zarovnají samy.
|
||||
> Je to jedno, pokud vždy začínají symbolem `>`.
|
||||
|
||||
@ -170,7 +147,7 @@ nebo
|
||||
2. Položka dvě
|
||||
3. Položka tři
|
||||
|
||||
<!-- Čísla ani nemusíte psát popořadě. Markdown je umí zobrazit správně, jenom
|
||||
<!-- Čísla ani nemusíte psát popořadě. Markdown je umí zobrazit správně, jenom
|
||||
je třeba vždy překontrolovat, že číslování funguje správně. -->
|
||||
|
||||
1. Položka jedna
|
||||
@ -215,7 +192,7 @@ Pro ještě hlubší odsazení můžete přidat další 4 mezery nebo další ta
|
||||
|
||||
```md
|
||||
moje_pole.each do |i|
|
||||
puts i
|
||||
puts i
|
||||
end
|
||||
```
|
||||
|
||||
@ -228,11 +205,13 @@ Honza neměl tušení, co dělá funkce `go_to()`!
|
||||
|
||||
V Markdownu od GitHubu, můžete použít speciální syntaxi pro kód:
|
||||
|
||||
<pre><code class="highlight">```ruby
|
||||
````md
|
||||
```ruby
|
||||
def neco
|
||||
puts "Ahoj světe!"
|
||||
puts "Ahoj světe!"
|
||||
end
|
||||
```</code></pre>
|
||||
```
|
||||
````
|
||||
|
||||
Text výše nepotřebuje čtyřmezerové odsazení a parser navíc použije zvýraznění
|
||||
syntaxe pro zvolený jazyk.
|
||||
@ -252,8 +231,8 @@ pomlček), a to buď s mezerami mezi jednotlivými znaky, nebo bez nich.
|
||||
## Odkazy
|
||||
|
||||
```md
|
||||
<!-- Jedna z nejlepších vlastností Markdownu je, jak snadno lze s jeho pomocí
|
||||
vytvářet odkazy. Text odkazu, který chcete zobrazit vložte do [] a hned za něj
|
||||
<!-- Jedna z nejlepších vlastností Markdownu je, jak snadno lze s jeho pomocí
|
||||
vytvářet odkazy. Text odkazu, který chcete zobrazit vložte do [] a hned za něj
|
||||
v kulatých závorkách () připojte url adresu. -->
|
||||
|
||||
[Klikni na mě!](http://test.com/)
|
||||
@ -277,12 +256,12 @@ v kulatých závorkách () připojte url adresu. -->
|
||||
[link1]: http://test.com/ "Cool!"
|
||||
[neco]: http://neco.czz/ "Dobře!"
|
||||
|
||||
<!-- Titulek v tomto případě může být v jednoduchých uvozovkách, závorkách, nebo
|
||||
zcela vynechaný. Reference může být kdekoliv ve vašem dokumentu a identifikátory
|
||||
<!-- Titulek v tomto případě může být v jednoduchých uvozovkách, závorkách, nebo
|
||||
zcela vynechaný. Reference může být kdekoliv ve vašem dokumentu a identifikátory
|
||||
mohou být jakékoli, pokud jsou unikátní. -->
|
||||
|
||||
|
||||
<!-- V markdownu existuje rovněž "implicitní pojmenování", které použije text
|
||||
<!-- V markdownu existuje rovněž "implicitní pojmenování", které použije text
|
||||
odkazu jako své id -->
|
||||
|
||||
[Toto][] je odkaz..
|
||||
@ -329,7 +308,7 @@ fungovat stejně.
|
||||
### Automatické odkazy
|
||||
|
||||
```md
|
||||
<http://stranka.cz/>
|
||||
<http://stranka.cz/>
|
||||
|
||||
je stejné jako
|
||||
|
||||
@ -345,14 +324,14 @@ je stejné jako
|
||||
### Escapování znaků
|
||||
|
||||
```md
|
||||
Chci napsat *tento text obklopený hvězdičkami*, ale protože nechci, aby to bylo
|
||||
Chci napsat *tento text obklopený hvězdičkami*, ale protože nechci, aby to bylo
|
||||
kurzívou, tak hvězdičky vyescapuji `\`: \*tento text bude obklopený hvězdičkami\*.
|
||||
```
|
||||
|
||||
### Klávesové zkratky
|
||||
|
||||
```md
|
||||
<!-- V Markdownu od GitHubu můžete použít tag <kbd> k označení kláves na
|
||||
<!-- V Markdownu od GitHubu můžete použít tag <kbd> k označení kláves na
|
||||
počítači -->
|
||||
|
||||
Váš počítač přestal pracovat? Zkuste
|
||||
|
@ -14,13 +14,9 @@ lang: cs-cz
|
||||
Python byl vytvořen Guidem Van Rossum v raných 90. letech. Nyní je jedním z nejpopulárnějších jazyků.
|
||||
Zamiloval jsem si Python pro jeho syntaktickou čistotu - je to vlastně spustitelný pseudokód.
|
||||
|
||||
Vaše zpětná vazba je vítána! Můžete mě zastihnout na [@louiedinh](http://twitter.com/louiedinh) nebo louiedinh [at] [email od googlu] anglicky,
|
||||
autora českého překladu pak na [@tbedrich](http://twitter.com/tbedrich) nebo ja [at] tbedrich.cz
|
||||
|
||||
Poznámka: Tento článek je zaměřen na Python 3. Zde se můžete [naučit starší Python 2.7](http://learnxinyminutes.com/docs/pythonlegacy/).
|
||||
|
||||
```python
|
||||
|
||||
# Jednořádkový komentář začíná křížkem
|
||||
|
||||
""" Víceřádkové komentáře používají tři uvozovky nebo apostrofy
|
||||
@ -78,9 +74,9 @@ False or True # => True
|
||||
0 and 2 # => 0
|
||||
-5 or 0 # => -5
|
||||
|
||||
# Při porovnání s boolean hodnotou nepoužívejte operátor rovnosti "==".
|
||||
# Při porovnání s boolean hodnotou nepoužívejte operátor rovnosti "==".
|
||||
# Stejně jako u hodnoty None.
|
||||
# Viz PEP8: https://www.python.org/dev/peps/pep-0008/
|
||||
# Viz PEP8: https://www.python.org/dev/peps/pep-0008/
|
||||
0 is False # => True
|
||||
2 is True # => False
|
||||
1 is True # => True
|
||||
@ -160,7 +156,7 @@ print("Jsem 3. Python 3.")
|
||||
nazev_promenne = 5
|
||||
nazev_promenne # => 5
|
||||
# Názvy proměnných mohou obsahovat i unicode znaky, ale nedělejte to.
|
||||
# Viz PEP 3131 -- Supporting Non-ASCII Identifiers:
|
||||
# Viz PEP 3131 -- Supporting Non-ASCII Identifiers:
|
||||
# https://www.python.org/dev/peps/pep-3131/
|
||||
název_proměnné = 5
|
||||
|
||||
@ -644,5 +640,6 @@ pozdrav("Pepo") # Vypíše 3x: "Měj se Pepo!"
|
||||
|
||||
## Co dál?
|
||||
|
||||
Spoustu odkazů na české i anglické materiály najdete na [webu české Python komunity]
|
||||
(http://python.cz/). Můžete také přijít na Pyvo, kde to společně probereme.
|
||||
Spoustu odkazů na české i anglické materiály najdete na
|
||||
[webu české Python komunity](http://python.cz/). Můžete
|
||||
také přijít na Pyvo, kde to společně probereme.
|
||||
|
@ -19,8 +19,6 @@ Tento tutoriál bude používat syntaxi CSS.
|
||||
Pokud jste již obeznámeni s CSS3, budete schopni používat Sass relativně rychle. Nezprostředkovává nějaké úplně nové stylové možnosti, spíše nátroje, jak psát Vás CSS kód více efektivně, udržitelně a jednoduše.
|
||||
|
||||
```scss
|
||||
|
||||
|
||||
//Jednořádkové komentáře jsou ze Sassu při kompilaci vymazány
|
||||
|
||||
/*Víceřádkové komentáře jsou naopak zachovány */
|
||||
@ -411,8 +409,6 @@ body {
|
||||
.gutter {
|
||||
width: 6.25%;
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
@ -867,7 +867,7 @@ on a new line! ""Wow!"", the masses cried";
|
||||
}
|
||||
|
||||
// It's also possible to define custom Indexers on objects.
|
||||
// All though this is not entirely useful in this example, you
|
||||
// Although this is not entirely useful in this example, you
|
||||
// could do bicycle[0] which returns "chris" to get the first passenger or
|
||||
// bicycle[1] = "lisa" to set the passenger. (of this apparent quattrocycle)
|
||||
private string[] passengers = { "chris", "phil", "darren", "regina" };
|
||||
@ -1311,7 +1311,6 @@ namespace Csharp7
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Topics Not Covered
|
||||
|
@ -69,6 +69,9 @@ div { }
|
||||
/* or ends with a value (CSS 3) */
|
||||
[attr$='ue'] { font-size:smaller; }
|
||||
|
||||
/* or contains a value (CSS 3) */
|
||||
[attr*='foo'] { }
|
||||
|
||||
/* or contains a value in a space-separated list */
|
||||
[otherAttr~='foo'] { }
|
||||
[otherAttr~='bar'] { }
|
||||
@ -125,6 +128,9 @@ selector:first-child {}
|
||||
/* any element that is the last child of its parent */
|
||||
selector:last-child {}
|
||||
|
||||
/* Select the nth child of selector parent (CSS 3) */
|
||||
selector:nth-child(n) { }
|
||||
|
||||
/* Just like pseudo classes, pseudo elements allow you to style certain parts of
|
||||
a document */
|
||||
|
||||
@ -144,6 +150,12 @@ selector::after {}
|
||||
in the group */
|
||||
selector1, selector2 { }
|
||||
|
||||
/* Select elements that do not have a certain state (CSS 3) */
|
||||
/* Here, we select div with no id attribute. */
|
||||
div:not([id]) {
|
||||
background-color: red;
|
||||
}
|
||||
|
||||
/* ####################
|
||||
## PROPERTIES
|
||||
#################### */
|
||||
@ -196,6 +208,41 @@ selector {
|
||||
/* if the first one is not found, the browser uses the next, and so on */
|
||||
font-family: "Courier New", Trebuchet, Arial, sans-serif;
|
||||
}
|
||||
|
||||
/* Custom CSS properties using variables (CSS 3) */
|
||||
:root {
|
||||
--main-bg-color: whitesmoke;
|
||||
}
|
||||
body {
|
||||
background-color: var(--main-bg-color)
|
||||
}
|
||||
|
||||
/* Perfom a calculation (CSS 3) */
|
||||
body {
|
||||
width: calc(100vw - 100px)
|
||||
}
|
||||
|
||||
/* Nest style rule inside another (CSS 3) */
|
||||
.main {
|
||||
.bgred { /* same as: .main .bgred { } */
|
||||
background: red;
|
||||
}
|
||||
& .bggreen { /* same as: .main .bggreen { } */
|
||||
background: green;
|
||||
}
|
||||
&.bgblue { /* (without space) same as: .main.bgblue { } */
|
||||
background: blue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Design responsive layout using flexbox (CSS 3) */
|
||||
.container {
|
||||
display: flex;
|
||||
flex-direction: row; /* in which direction stack the flex items */
|
||||
flex-wrap: wrap; /* whether or not flex items should wrap */
|
||||
justify-content: center; /* how to align flex items horizontally */
|
||||
align-items: center; /* how to align flex items vertically */
|
||||
}
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
name: CUE
|
||||
category: language
|
||||
language: cue
|
||||
language: CUE
|
||||
filename: learncue.cue
|
||||
contributors:
|
||||
- ["Daniel Cox", "https://github.com/danielpcox"]
|
||||
@ -23,8 +23,9 @@ disposition: "oblivious"
|
||||
```
|
||||
|
||||
Now we can unify and export to JSON:
|
||||
|
||||
```bash
|
||||
% cue export name.cue disposition.cue
|
||||
% cue export name.cue disposition.cue
|
||||
{
|
||||
"name": "Daniel",
|
||||
"disposition": "oblivious"
|
||||
@ -32,8 +33,9 @@ Now we can unify and export to JSON:
|
||||
```
|
||||
|
||||
Or YAML:
|
||||
|
||||
```bash
|
||||
% cue export --out yaml name.cue disposition.cue
|
||||
% cue export --out yaml name.cue disposition.cue
|
||||
name: Daniel
|
||||
disposition: oblivious
|
||||
```
|
||||
@ -58,7 +60,7 @@ foo: 100
|
||||
```
|
||||
|
||||
```bash
|
||||
% cue export string_value.cue integer_value.cue
|
||||
% cue export string_value.cue integer_value.cue
|
||||
foo: conflicting values "baz" and 100 (mismatched types string and int):
|
||||
integer_value.cue:1:6
|
||||
string_value.cue:1:6
|
||||
@ -220,7 +222,7 @@ vatican_city: #Country & {
|
||||
}
|
||||
```
|
||||
|
||||
CUE may save you quite a bit of time with all the sugar it provides on top of mere JSON. Here we're defining, "modifying", and validating a nested structure in three lines: (Notice the `[]` syntax used around `string` to signal to the engine that `string` is a constraint, not a string in this case.)
|
||||
CUE may save you quite a bit of time with all the sugar it provides on top of mere JSON. Here we're defining, "modifying", and validating a nested structure in three lines: (Notice the `[]` syntax used around `string` to signal to the engine that `string` is a constraint, not a string in this case.)
|
||||
|
||||
```yaml
|
||||
//paths.cue
|
||||
@ -386,7 +388,7 @@ j: 8 < 10 // and supports boolean ops
|
||||
price: number
|
||||
// Require a justification if price is too high
|
||||
if price > 100 {
|
||||
justification: string
|
||||
justification: string
|
||||
}
|
||||
price: 200
|
||||
justification: "impulse buy"
|
||||
@ -398,11 +400,11 @@ comp: [ for x in #items if x rem 2 == 0 {x*x}]
|
||||
// and... well you can do this too
|
||||
#a: [ "Apple", "Google", "SpaceX"]
|
||||
for k, v in #a {
|
||||
"\( strings.ToLower(v) )": {
|
||||
pos: k + 1
|
||||
name: v
|
||||
nameLen: len(v)
|
||||
}
|
||||
"\( strings.ToLower(v) )": {
|
||||
pos: k + 1
|
||||
name: v
|
||||
nameLen: len(v)
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
@ -479,7 +481,7 @@ This creates a `cue.mod/` subdirectory within that `mymodule` directory, and `cu
|
||||
- gen/
|
||||
- usr/
|
||||
|
||||
For a different perspective on this and details about what's in there, see https://cuelang.org/docs/concepts/packages/. For my purposes here, I'll say you don't need to think about the contents of this directory *at all*, except that your module name will be the prefix for all imports within your module.
|
||||
For a different perspective on this and details about what's in there, see [cuelang.org/docs/concepts/packages/](https://cuelang.org/docs/concepts/packages/). For my purposes here, I'll say you don't need to think about the contents of this directory *at all*, except that your module name will be the prefix for all imports within your module.
|
||||
|
||||
Where will your module file hierarchy go? All files and directories for your module are rooted in `mymodule/`, the directory that also contains `cue.mod/`. If you want to import a package, you'll prefix it with `example.com/mymodule`, followed by a relative path rooted in `mymodule/`.
|
||||
|
||||
@ -546,6 +548,6 @@ configuredBar: conflicting values string and 200 (mismatched types string and in
|
||||
|
||||
That's it for now. I understand there are more package management features coming in the future and the design decisions around `cue.mod` are looking ahead to that.
|
||||
|
||||
Finally, CUE has built-in modules with powerful functionality. We saw one of these earlier, when we imported "strings" and used `strings.ToLower`. Imports without fully-qualified module names are assumed to be built-ins. The full list and documentation for each is here: https://pkg.go.dev/cuelang.org/go/pkg
|
||||
Finally, CUE has built-in modules with powerful functionality. We saw one of these earlier, when we imported "strings" and used `strings.ToLower`. Imports without fully-qualified module names are assumed to be built-ins. The full list and documentation for each is here: [pkg.go.dev/cuelang.org/go/pkg](https://pkg.go.dev/cuelang.org/go/pkg)
|
||||
|
||||
This has been a condensation of the official docs and tutorials, so go give the source material some love: https://cuelang.org/docs/tutorials/
|
||||
This has been a condensation of the official docs and tutorials, so go give the source material some love: [cuelang.org/docs/tutorials/](https://cuelang.org/docs/tutorials/)
|
||||
|
@ -5,84 +5,57 @@ contributors:
|
||||
- ["Théo Gauchoux", "https://github.com/TheoGauchoux"]
|
||||
---
|
||||
|
||||
Cypher is the Neo4j’s query language to manipulate graphs easily. It reuses syntax from SQL and mixes it with kind of ascii-art to represent graphs.
|
||||
Cypher is Neo4j's query language for easily manipulating graphs.
|
||||
It reuses syntax from SQL and mixes it with kind of an ASCII-art to represent graphs.
|
||||
This tutorial assumes that you already know graph concepts like nodes and relationships.
|
||||
|
||||
[Read more here.](https://neo4j.com/developer/cypher-query-language/)
|
||||
## Nodes represent a record in a graph
|
||||
|
||||
`()` is an empty *node*, to indicate that there is a *node*, but it's not relevant for the query.
|
||||
|
||||
Nodes
|
||||
---
|
||||
`(n)` is a *node* referred by the variable `n`, reusable in the query. It begins with lowercase and uses camelCase.
|
||||
|
||||
**Represents a record in a graph.**
|
||||
`(p:Person)` - you can add a *label* to your node, here `Person`. It's like a type/class/category. It begins with uppercase and uses camelCase.
|
||||
|
||||
`()`
|
||||
It's an empty *node*, to indicate that there is a *node*, but it's not relevant for the query.
|
||||
`(p:Person:Manager)` - a node can have many *labels*.
|
||||
|
||||
`(n)`
|
||||
It's a *node* referred by the variable **n**, reusable in the query. It begins with lowercase and uses camelCase.
|
||||
`(p:Person {name : 'Théo Gauchoux', age : 22})` - a node can have some *properties*, here `name` and `age`. It begins with lowercase and uses camelCase.
|
||||
|
||||
`(p:Person)`
|
||||
You can add a *label* to your node, here **Person**. It's like a type / a class / a category. It begins with uppercase and uses camelCase.
|
||||
The types allowed in properties:
|
||||
|
||||
`(p:Person:Manager)`
|
||||
A node can have many *labels*.
|
||||
- Numeric
|
||||
- Boolean
|
||||
- String
|
||||
- List of previous primitive types
|
||||
|
||||
`(p:Person {name : 'Théo Gauchoux', age : 22})`
|
||||
A node can have some *properties*, here **name** and **age**. It begins with lowercase and uses camelCase.
|
||||
*Warning: there's no datetime properties in Cypher! You can use a String with a specific pattern or a Numeric from a specific date.*
|
||||
|
||||
The types allowed in properties :
|
||||
`p.name` - you can access a property with the dot style.
|
||||
|
||||
- Numeric
|
||||
- Boolean
|
||||
- String
|
||||
- List of previous primitive types
|
||||
## Relationships (or Edges) connect two nodes
|
||||
|
||||
*Warning : there isn't datetime property in Cypher ! You can use String with a specific pattern or a Numeric from a specific date.*
|
||||
`[:KNOWS]` is a *relationship* with the *label* `KNOWS`. It's a *label* as the node's label. It uses UPPER\_SNAKE\_CASE.
|
||||
|
||||
`p.name`
|
||||
You can access to a property with the dot style.
|
||||
`[k:KNOWS]` - the same *relationship*, referred by the variable `k`, reusable in the query, but it's not necessary.
|
||||
|
||||
`[k:KNOWS {since:2017}]` - the same *relationship*, with *properties* (like *node*), here `since`.
|
||||
|
||||
Relationships (or Edges)
|
||||
---
|
||||
`[k:KNOWS*..4]` is structural information to use in a *path* (seen later). Here, `\*..4` says "Match the pattern, with the relationship `k` which can be repeated between 1 and 4 times.
|
||||
|
||||
**Connects two nodes**
|
||||
## Paths - the way to mix nodes and relationships.
|
||||
|
||||
`[:KNOWS]`
|
||||
It's a *relationship* with the *label* **KNOWS**. It's a *label* as the node's label. It begins with uppercase and use UPPER\_SNAKE\_CASE.
|
||||
`(a:Person)-[:KNOWS]-(b:Person)` - a path describing that `a` and `b` know each other.
|
||||
|
||||
`[k:KNOWS]`
|
||||
The same *relationship*, referred by the variable **k**, reusable in the query, but it's not necessary.
|
||||
`(a:Person)-[:MANAGES]->(b:Person)` - a path can be directed. This path describes that `a` is the manager of `b`.
|
||||
|
||||
`[k:KNOWS {since:2017}]`
|
||||
The same *relationship*, with *properties* (like *node*), here **since**.
|
||||
`(a:Person)-[:KNOWS]-(b:Person)-[:KNOWS]-(c:Person)` - you can chain multiple relationships. This path describes the friend of a friend.
|
||||
|
||||
`[k:KNOWS*..4]`
|
||||
It's a structural information to use in a *path* (seen later). Here, **\*..4** says "Match the pattern, with the relationship **k** which be repeated between 1 and 4 times.
|
||||
`(a:Person)-[:MANAGES]->(b:Person)-[:MANAGES]->(c:Person)` - a chain can also be directed. This path describes that `a` is the boss of `b` and the big boss of `c`.
|
||||
|
||||
Commonly used patterns (from Neo4j documentation):
|
||||
|
||||
Paths
|
||||
---
|
||||
|
||||
**The way to mix nodes and relationships.**
|
||||
|
||||
`(a:Person)-[:KNOWS]-(b:Person)`
|
||||
A path describing that **a** and **b** know each other.
|
||||
|
||||
`(a:Person)-[:MANAGES]->(b:Person)`
|
||||
A path can be directed. This path describes that **a** is the manager of **b**.
|
||||
|
||||
`(a:Person)-[:KNOWS]-(b:Person)-[:KNOWS]-(c:Person)`
|
||||
You can chain multiple relationships. This path describes the friend of a friend.
|
||||
|
||||
`(a:Person)-[:MANAGES]->(b:Person)-[:MANAGES]->(c:Person)`
|
||||
A chain can also be directed. This path describes that **a** is the boss of **b** and the big boss of **c**.
|
||||
|
||||
Patterns often used (from Neo4j doc) :
|
||||
|
||||
```
|
||||
// Friend-of-a-friend
|
||||
```cypher
|
||||
// Friend-of-a-friend
|
||||
(user)-[:KNOWS]-(friend)-[:KNOWS]-(foaf)
|
||||
|
||||
// Shortest path
|
||||
@ -91,159 +64,167 @@ path = shortestPath( (user)-[:KNOWS*..5]-(other) )
|
||||
// Collaborative filtering
|
||||
(user)-[:PURCHASED]->(product)<-[:PURCHASED]-()-[:PURCHASED]->(otherProduct)
|
||||
|
||||
// Tree navigation
|
||||
// Tree navigation
|
||||
(root)<-[:PARENT*]-(leaf:Category)-[:ITEM]->(data:Product)
|
||||
|
||||
```
|
||||
|
||||
|
||||
Create queries
|
||||
---
|
||||
## Create queries
|
||||
|
||||
Create a new node
|
||||
```
|
||||
|
||||
```cypher
|
||||
CREATE (a:Person {name:"Théo Gauchoux"})
|
||||
RETURN a
|
||||
```
|
||||
|
||||
*`RETURN` allows to have a result after the query. It can be multiple, as `RETURN a, b`.*
|
||||
|
||||
Create a new relationship (with 2 new nodes)
|
||||
```
|
||||
|
||||
```cypher
|
||||
CREATE (a:Person)-[k:KNOWS]-(b:Person)
|
||||
RETURN a,k,b
|
||||
```
|
||||
|
||||
Match queries
|
||||
---
|
||||
## Match queries
|
||||
|
||||
Match all nodes
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (n)
|
||||
RETURN n
|
||||
```
|
||||
|
||||
Match nodes by label
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (a:Person)
|
||||
RETURN a
|
||||
```
|
||||
|
||||
Match nodes by label and property
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (a:Person {name:"Théo Gauchoux"})
|
||||
RETURN a
|
||||
```
|
||||
|
||||
Match nodes according to relationships (undirected)
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (a)-[:KNOWS]-(b)
|
||||
RETURN a,b
|
||||
```
|
||||
|
||||
Match nodes according to relationships (directed)
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (a)-[:MANAGES]->(b)
|
||||
RETURN a,b
|
||||
```
|
||||
|
||||
Match nodes with a `WHERE` clause
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (p:Person {name:"Théo Gauchoux"})-[s:LIVES_IN]->(city:City)
|
||||
WHERE s.since = 2015
|
||||
RETURN p,state
|
||||
```
|
||||
|
||||
You can use `MATCH WHERE` clause with `CREATE` clause
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (a), (b)
|
||||
WHERE a.name = "Jacquie" AND b.name = "Michel"
|
||||
CREATE (a)-[:KNOWS]-(b)
|
||||
```
|
||||
|
||||
|
||||
Update queries
|
||||
---
|
||||
## Update queries
|
||||
|
||||
Update a specific property of a node
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (p:Person)
|
||||
WHERE p.name = "Théo Gauchoux"
|
||||
SET p.age = 23
|
||||
```
|
||||
|
||||
Replace all properties of a node
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (p:Person)
|
||||
WHERE p.name = "Théo Gauchoux"
|
||||
SET p = {name: "Michel", age: 23}
|
||||
```
|
||||
|
||||
Add new property to a node
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (p:Person)
|
||||
WHERE p.name = "Théo Gauchoux"
|
||||
SET p + = {studies: "IT Engineering"}
|
||||
SET p += {studies: "IT Engineering"}
|
||||
```
|
||||
|
||||
Add a label to a node
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (p:Person)
|
||||
WHERE p.name = "Théo Gauchoux"
|
||||
SET p:Internship
|
||||
```
|
||||
|
||||
|
||||
Delete queries
|
||||
---
|
||||
## Delete queries
|
||||
|
||||
Delete a specific node (linked relationships must be deleted before)
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (p:Person)-[relationship]-()
|
||||
WHERE p.name = "Théo Gauchoux"
|
||||
DELETE relationship, p
|
||||
```
|
||||
|
||||
Remove a property in a specific node
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (p:Person)
|
||||
WHERE p.name = "Théo Gauchoux"
|
||||
REMOVE p.age
|
||||
```
|
||||
*Pay attention to the `REMOVE`keyword, it's not `DELETE` !*
|
||||
|
||||
*Pay attention to the `REMOVE` keyword, it's not `DELETE`!*
|
||||
|
||||
Remove a label from a specific node
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (p:Person)
|
||||
WHERE p.name = "Théo Gauchoux"
|
||||
DELETE p:Person
|
||||
```
|
||||
|
||||
Delete entire database
|
||||
```
|
||||
|
||||
```cypher
|
||||
MATCH (n)
|
||||
OPTIONAL MATCH (n)-[r]-()
|
||||
DELETE n, r
|
||||
```
|
||||
*Seriously, it's the `rm -rf /` of Cypher !*
|
||||
|
||||
*Seriously, it's the `rm -rf /` of Cypher!*
|
||||
|
||||
Other useful clauses
|
||||
---
|
||||
## Other useful clauses
|
||||
|
||||
`PROFILE`
|
||||
Before a query, show the execution plan of it.
|
||||
`PROFILE` - before a query, show its execution plan.
|
||||
|
||||
`COUNT(e)`
|
||||
Count entities (nodes or relationships) matching **e**.
|
||||
`COUNT(e)` - count entities (nodes or relationships) matching `e`.
|
||||
|
||||
`LIMIT x`
|
||||
Limit the result to the x first results.
|
||||
`LIMIT x` - limit the result to the first `x` results.
|
||||
|
||||
## Special hints
|
||||
|
||||
Special hints
|
||||
---
|
||||
|
||||
- There is just single-line comments in Cypher, with double-slash : // Comments
|
||||
- You can execute a Cypher script stored in a **.cql** file directly in Neo4j (it's an import). However, you can't have multiple statements in this file (separated by **;**).
|
||||
- Cypher only has single-line comments, using double-slashes: `// comment`
|
||||
- You can execute a Cypher script stored in a .cql file directly in Neo4j (it's an import). However, you can't have multiple statements in this file (separated by `;`).
|
||||
- Use the Neo4j shell to write Cypher, it's really awesome.
|
||||
- The Cypher will be the standard query language for all graph databases (known as **OpenCypher**).
|
||||
- Cypher will be the standard query language for all graph databases (known as [openCypher](https://opencypher.org/)).
|
||||
|
||||
Read more [here](https://neo4j.com/developer/cypher-query-language/).
|
||||
|
||||
|
@ -3,7 +3,6 @@ language: D
|
||||
filename: learnd.d
|
||||
contributors:
|
||||
- ["Nick Papanastasiou", "www.nickpapanastasiou.github.io"]
|
||||
|
||||
---
|
||||
|
||||
```d
|
||||
@ -128,7 +127,6 @@ class Matrix(uint m, uint n, T = int) {
|
||||
}
|
||||
|
||||
auto mat = new Matrix!(3, 3); // We've defaulted type 'T' to 'int'.
|
||||
|
||||
```
|
||||
|
||||
Speaking of classes, let's talk about properties for a second. A property
|
||||
|
@ -32,7 +32,7 @@ import "dart:math" as math;
|
||||
// Single line comment
|
||||
/**
|
||||
* Multi-line comment
|
||||
* Can comment more than 2 lines
|
||||
* Can comment several lines
|
||||
*/
|
||||
/// Code doc comment
|
||||
/// It uses markdown syntax to generate code docs when making an API.
|
||||
@ -254,25 +254,29 @@ example10() {
|
||||
/// `int` and `double` are children of type `num`
|
||||
example11() {
|
||||
var i = 1 + 320, d = 3.2 + 0.01;
|
||||
final num myFinalNumDouble = 2.2;
|
||||
final num myFinalNumInt = 2;
|
||||
final int myFinalInt = 1;
|
||||
final double myFinalDouble = 0.1;
|
||||
num myNumDouble = 2.2;
|
||||
num myNumInt = 2;
|
||||
int myInt = 1;
|
||||
double myDouble = 0; // Dart will add decimal prefix, becomes 0.0;
|
||||
myNumDouble = myInt; // valid
|
||||
myNumDouble = myDouble; //valid
|
||||
myNumDouble = myNumInt; //valid
|
||||
myNumDouble = myFinalInt; // valid
|
||||
myNumDouble = myFinalDouble; // valid
|
||||
myNumDouble = myFinalNumInt; // valid
|
||||
|
||||
myNumInt = myInt; // valid
|
||||
myNumInt = myDouble; // valid
|
||||
myNumInt = myNumDouble; // valid
|
||||
myNumInt = myFinalInt; // valid
|
||||
myNumInt = myFinalDouble; // valid
|
||||
myNumInt = myFinalNumDouble; // valid
|
||||
|
||||
myInt = myNumDouble; //Error
|
||||
myInt = myDouble; //Error
|
||||
myInt = myNumInt; //valid
|
||||
myInt = myNumDouble; // error
|
||||
myInt = myFinalDouble; // error
|
||||
myInt = myFinalNumInt; // valid
|
||||
|
||||
myDouble = myInt; //error
|
||||
myDouble = myNumInt; //valid
|
||||
myDouble = myNumDouble; //valid
|
||||
myDouble = myFinalInt; // error
|
||||
myDouble = myFinalNumInt; // error
|
||||
myDouble = myFinalNumDouble; // valid
|
||||
|
||||
print("Example11 int ${i}");
|
||||
print("Example11 double ${d}");
|
||||
@ -308,15 +312,15 @@ example14() {
|
||||
if (a) {
|
||||
print("true, a is $a");
|
||||
}
|
||||
a = null;
|
||||
a = false;
|
||||
if (a) {
|
||||
print("true, a is $a");
|
||||
print("true, a is $a");
|
||||
} else {
|
||||
print("false, a is $a"); /// runs here
|
||||
}
|
||||
|
||||
/// dynamic typed null can be convert to bool
|
||||
var b;/// b is dynamic type
|
||||
/// dynamic typed null can not be convert to bool
|
||||
var b; /// b is dynamic type
|
||||
b = "abc";
|
||||
try {
|
||||
if (b) {
|
||||
@ -327,17 +331,17 @@ example14() {
|
||||
} catch (e) {
|
||||
print("error, b is $b"); /// this could be run but got error
|
||||
}
|
||||
b = null;
|
||||
if (b) {
|
||||
b = null;
|
||||
if (b) { /// Failed assertion: boolean expression must not be null)
|
||||
print("true, b is $b");
|
||||
} else {
|
||||
print("false, b is $b"); /// runs here
|
||||
print("false, b is $b");
|
||||
}
|
||||
|
||||
/// statically typed null can not be convert to bool
|
||||
var c = "abc";
|
||||
c = null;
|
||||
/// complie failed
|
||||
/// compilation failed
|
||||
/// if (c) {
|
||||
/// print("true, c is $c");
|
||||
/// } else {
|
||||
@ -710,7 +714,6 @@ main() {
|
||||
example30 // Adding this comment stops the dart formatter from putting all items on a new line
|
||||
].forEach((ef) => ef());
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Further Reading
|
||||
|
@ -8,9 +8,9 @@ filename: asciidoc-de.adoc
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
AsciiDoc ist eine Auszeichnungssprache ähnlich zu Markdown. Sie kann für alles
|
||||
verwendet werden von Büchern zu Blogs. Erfunden wurde sie 2002 von Stuart
|
||||
Rackham. Die Sprache ist simpel aber sie ermöglicht eine große Anzahl an
|
||||
AsciiDoc ist eine Auszeichnungssprache, ähnlich wie Markdown. Sie kann für alles
|
||||
verwendet werden von Büchern bis zu Blogs. Erfunden wurde sie 2002 von Stuart
|
||||
Rackham. Die Sprache ist simpel, aber sie ermöglicht eine große Anzahl an
|
||||
Anpassungen.
|
||||
|
||||
Kopfzeile des Dokuments
|
||||
@ -57,12 +57,12 @@ Dieser Artikel über Chips wird Spaß machen.
|
||||
Absätze
|
||||
|
||||
```
|
||||
Du musst nichts besonderes machen für Absätze.
|
||||
Du musst nichts Besonderes machen für Absätze.
|
||||
|
||||
Füge eine Leerzeile zwischen zwei Absätze, um sie zu trennen.
|
||||
|
||||
Um eine Leerzeile zu erhalten musst du ein +
|
||||
ergänzen und du erhälst einen Umbruch!
|
||||
ergänzen und du erhältst einen Umbruch!
|
||||
```
|
||||
|
||||
Textformatierung
|
||||
@ -87,7 +87,6 @@ Abteilungstitel
|
||||
==== Level 3 <h4>
|
||||
|
||||
===== Level 4 <h5>
|
||||
|
||||
```
|
||||
|
||||
Listen
|
||||
|
@ -160,7 +160,7 @@ echo "#helloworld" | tee output.out >/dev/null
|
||||
# (mit '-i' für "interactive" erfolgt für jede Datei eine Rückfrage)
|
||||
rm -v output.out error.err output-and-error.log
|
||||
|
||||
# Die Ausgabe von Befehlen kann mit Hilfe von $( ) in anderen Befehlen verwendet weden:
|
||||
# Die Ausgabe von Befehlen kann mithilfe von $( ) in anderen Befehlen verwendet werden:
|
||||
# Der folgende Befehl zeigt die Anzahl aller Dateien und Unterverzeichnisse
|
||||
# im aktuellen Verzeichnis an.
|
||||
echo "Dieser Ordner beinhaltet $(ls | wc -l) Dateien und Verzeichnisse."
|
||||
|
@ -5,8 +5,9 @@ contributors:
|
||||
filename: learnbc-de.bc
|
||||
lang: de-de
|
||||
---
|
||||
```c
|
||||
/* Das is ein mehr-
|
||||
|
||||
```bc
|
||||
/* Das ist ein mehr-
|
||||
zeiliger Kommentar */
|
||||
# Das ist ein (einzeiliger) Kommentar (in GNU bc).
|
||||
|
||||
@ -14,11 +15,11 @@ zeiliger Kommentar */
|
||||
num = 45 /* Alle Variablen speichern nur Doubles und es ist
|
||||
nicht möglich String-Konstanten direkt zu speichern */
|
||||
num = 45; /* Es kann nach jedem Statement ein optionales Semikolon
|
||||
hinzugefügt werden */
|
||||
hinzugefügt werden */
|
||||
/* Blöcke werden mit den Operatoren {} (ähnlich wie in C) bezeichnet */
|
||||
while(num < 50) {
|
||||
num += 1 /* äquivalent zu num=num+1.
|
||||
a = a Op b ist äquivalent zu a Op= b*/
|
||||
num += 1 /* äquivalent zu num=num+1.
|
||||
a = a Op b ist äquivalent zu a Op= b*/
|
||||
}
|
||||
/* Ausserdem gibt es ++ (Inkrement) und -- (Dekrement) Operatoren */
|
||||
/* Es gibt 3 spezielle Variablen:
|
||||
@ -30,21 +31,21 @@ hour = read() /*Eingabe einer Zahl*/
|
||||
|
||||
if(hour < 12) { /*Operatoren sind genau wie in C*/
|
||||
print "Guten Morgen\n" /*"print" Gibt Strings oder Variablen
|
||||
mit einem Komma separiert aus.*/
|
||||
mit einem Komma separiert aus.*/
|
||||
} else if(hour == 12) {
|
||||
print "Hallo\n"
|
||||
/* Escape-Sequenzen starten mite einem \ in einem String.
|
||||
Um Escape-Sequenzen klarer zu machen, ist hier eine vereinfachte
|
||||
Liste, welche in bc funktioneren.:
|
||||
/* Escape-Sequenzen starten mit einem \ in einem String.
|
||||
Um Escape-Sequenzen klarer zu machen, ist hier eine vereinfachte
|
||||
Liste, welche in bc funktionieren:
|
||||
\b: Backspace
|
||||
\c: carriage return
|
||||
\n: Zeilenumbruch
|
||||
\t: Tab
|
||||
\\: Backslash*/
|
||||
} else {
|
||||
/* Standardmässig sind Variablen global. */
|
||||
/* Standardmässig sind Variablen global. */
|
||||
thisIsGlobal = 5
|
||||
/*Variablen können lokal gemacht werden. Benutze das Schlüsselwort "auto"
|
||||
/*Variablen können lokal gemacht werden. Benutze das Schlüsselwort "auto"
|
||||
in einer Funktion.*/
|
||||
}
|
||||
|
||||
@ -55,7 +56,7 @@ num = blankVariable /*num wurde auf 0 gesetzt.*/
|
||||
if(!num) {print "false\n"}
|
||||
|
||||
/*Im Gegensatz zu C hat bc den Ternäroperator ?: nicht. Zum Beispiel
|
||||
führt dieser Codeblok zu einem Fehler:
|
||||
führt dieser Codeblock zu einem Fehler:
|
||||
a = (num) ? 1 : 0
|
||||
Jedoch kann dies simuliert werden:*/
|
||||
a = (num) && (1) || (0) /*&& ist das UND, || ist das ODER*/
|
||||
@ -78,7 +79,7 @@ define fac(n) { /*Definiere eine Funktion mit define*/
|
||||
|
||||
num = fac(4) /*24*/
|
||||
|
||||
/*Dies ist ein Beispiel von lokalen Variabeln.*/
|
||||
/*Dies ist ein Beispiel von lokalen Variablen.*/
|
||||
define x(n) {
|
||||
auto x
|
||||
x = 1
|
||||
@ -96,7 +97,7 @@ print a[0], " ", a[1], " ", a[2], " ", a[3], "\n"
|
||||
quit /* Füge diese Codezeile hinzu, um sicherzustellen, dass
|
||||
das Programm beendet. Diese Codezeile ist optional.*/
|
||||
```
|
||||
|
||||
Viel Spass mit diesem einfachen Rechner! (Oder dieser Programmiersprache, um exakt zu sein.)
|
||||
|
||||
Das ganze Programm wurde in GNU bc geschrieben. Um es auszuführen, benutze ```bc learnbc.bc```.
|
||||
|
||||
|
@ -19,7 +19,7 @@ Brainfuck im Browser ausprobiert werden.
|
||||
```
|
||||
Alle Zeichen außer "><+-.,[]" (ohne die Klammern) werden ignoriert.
|
||||
|
||||
Brainfuck besteht aus einem Array mit unendlich vielen Elementen, die alle mit Null initalisiert
|
||||
Brainfuck besteht aus einem Array mit unendlich vielen Elementen, die alle mit Null initialisiert
|
||||
sind und einem Datenzeiger auf das aktuelle Element.
|
||||
|
||||
Es gibt acht Befehle:
|
||||
@ -29,10 +29,10 @@ Es gibt acht Befehle:
|
||||
< : Bewegt den Zeiger um eine Stelle zurück.
|
||||
. : Gibt den Wert der aktuellen Zelle als ASCII Wert aus (z.B. 65 = 'A').
|
||||
, : Liest ein einzelnes Zeichen von der Standardeingabe und speichert dessen ASCII Wert in der aktuellen Zelle.
|
||||
[ : Wenn der Wert des aktuellen Elements Null ist, bewege des Zeiger hinter den
|
||||
[ : Wenn der Wert des aktuellen Elements Null ist, bewege den Zeiger hinter den
|
||||
zugehörigen ]-Befehl.
|
||||
Ansonsten, bewege den Zeiger ein Element weiter.
|
||||
] : Wenn der Wert des aktuellen Elements Null ist, bewege des Zeiger um eine Stelle
|
||||
] : Wenn der Wert des aktuellen Elements Null ist, bewege den Zeiger um eine Stelle
|
||||
weiter.
|
||||
Ansonsten, bewege den Zeiger hinter den zugehörigen [-Befehl.
|
||||
|
||||
@ -51,7 +51,7 @@ und das Programm hinter dem korrespondierenden ] fortgesetzt).
|
||||
|
||||
An dieser Stelle befinden wir uns an Zelle #1, die jetzt den Wert 0 hat, während Zelle #2
|
||||
den Wert 60 hat. Wir gehen vor zu Zelle #2, inkrementieren 5 Mal, bis zum Wert 65,
|
||||
und geben dann den Wert der Zelle #2 aus. 65 ist ein 'A' im ASCII Zeichensatz,
|
||||
und geben dann den Wert der Zelle #2 aus. 65 ist ein 'A' im ASCII-Zeichensatz,
|
||||
daher wird 'A' am Terminal ausgegeben..
|
||||
|
||||
|
||||
@ -59,11 +59,11 @@ daher wird 'A' am Terminal ausgegeben..
|
||||
|
||||
Dieses Programm liest ein Zeichen von der Benutzereingabe und schreibt dessen Wert
|
||||
in Zelle #1. Danach beginnt eine Schleife. Rücke vor auf Zelle #2, erhöhe den Wert der Zelle #2,
|
||||
gehe zurück auf Zelle #1, verringere den Wert der Zelle #1. Dies geht solange bis
|
||||
gehe zurück auf Zelle #1, verringere den Wert der Zelle #1. Dies geht so lange bis
|
||||
Zelle #1 den Wert 0 und Zelle #2 den alten Wert aus #1 hat. Da wir am Ende der Schleife
|
||||
bie Zelle #1 sind, gehe vor zu Zelle #2 und gibt denb Wert als ASCII Zeichen aus.
|
||||
bei Zelle #1 sind, gehe vor zu Zelle #2 und gibt den Wert als ASCII Zeichen aus.
|
||||
|
||||
Beachte biite, dass die Leerzeichen nur aus Gründen der Lesbarkeit geschrieben werden.
|
||||
Beachte bitte, dass die Leerzeichen nur aus Gründen der Lesbarkeit geschrieben werden.
|
||||
Man könnte genauso schreiben:
|
||||
|
||||
,[>+<-]>.
|
||||
@ -84,6 +84,6 @@ Am Ende steht in Zelle #3 das Ergebnis.
|
||||
```
|
||||
|
||||
Das ist Brainfuck. Nicht so schwierig, oder? Zum Spaß kannst du dein eigenes Brainfuck
|
||||
Programm schreiben oder du schreibst einen Brainfuck Interpreter in einer anderen
|
||||
Programm schreiben oder du schreibst einen Brainfuck-Interpreter in einer anderen
|
||||
Programmiersprache. Der Interpreter lässt sich ziemlich einfach implementieren.
|
||||
Falls du Masochist bist, kannst du auch versuchen, einen Brainfuck Interpreter in Brainfuck zu implementieren.
|
||||
Falls du Masochist bist, kannst du auch versuchen, einen Brainfuck-Interpreter in Brainfuck zu implementieren.
|
@ -278,7 +278,7 @@ string retVal = tempObjectFun();
|
||||
// - ein String Objekt wird von "tempObjectFun" zurückgegeben
|
||||
// - ein neuer String wird mit dem zurückgegebenen Objekt als Argument für den Konstruktor erzeugt.
|
||||
// - das zurückgegebene Objekt wird zerstört
|
||||
// Das zurückgegbene Objekt wird temporäres Objekt genannt. Temporäre Objekte werden erzeugt
|
||||
// Das zurückgegebene Objekt wird temporäres Objekt genannt. Temporäre Objekte werden erzeugt
|
||||
// wann immer eine Funktion ein Objekt zurückgibt. Zerstört werden diese am Ende der Auswertung des Ausdrucks
|
||||
// (dies schreibt der Standard vor, aber Compiler sind berechtigt dieses Verhalten zu ändern. Siehe "return value optimization"
|
||||
// für Details). Wie in diesem Code:
|
||||
@ -530,7 +530,7 @@ public:
|
||||
Point (double a, double b) :
|
||||
x(a),
|
||||
y(b)
|
||||
{ /* Außschließliche Initialisierung der Werte */ }
|
||||
{ /* Ausschließliche Initialisierung der Werte */ }
|
||||
|
||||
// Überladung des "+" Operator.
|
||||
Point operator+(const Point& rhs) const;
|
||||
@ -842,7 +842,7 @@ for (int i = 0; i < my_vector.size(); i++)
|
||||
}
|
||||
|
||||
// Oder die Verwendung von Iteratoren:
|
||||
vector<string>::iterator it; // Initialisierng des Iterators.
|
||||
vector<string>::iterator it; // Initialisierung des Iterators.
|
||||
for (it = my_vector.begin(); it != my_vector.end(); ++it)
|
||||
{
|
||||
cout << *it << endl;
|
||||
@ -913,7 +913,7 @@ for (it=mymap.begin(); it!=mymap.end(); ++it)
|
||||
it = mymap.find('Z');
|
||||
cout << it->second;
|
||||
|
||||
// Ausabe: 26
|
||||
// Ausgabe: 26
|
||||
|
||||
// Bemerkung: für "hash maps" sollten die "unordered_map´s" verwendet werden. Diese
|
||||
// sind effizienter und benötigen keine Reihenfolge. "unordered_maps" sind ab
|
||||
@ -1148,9 +1148,8 @@ compl 4 // Führt bitweises nicht aus.
|
||||
4 bitor 3 // Führt bitweises oder aus.
|
||||
4 bitand 3 // Führt bitweises und aus.
|
||||
4 xor 3 // Führt bitweises xor aus.
|
||||
|
||||
|
||||
```
|
||||
|
||||
Weiterführende Literatur:
|
||||
|
||||
* Aktuelle Sprachen-Referenz [CPP Reference](http://cppreference.com/w/cpp).
|
||||
|
@ -8,7 +8,7 @@ lang: de-de
|
||||
|
||||
Ach, C. Immer noch **die** Sprache für modernes High-Performance Computing.
|
||||
|
||||
C ist wahrscheinlich die Programmiersprache mit dem niedrigsten Abstraktionsnvieau,
|
||||
C ist wahrscheinlich die Programmiersprache mit dem niedrigsten Abstraktionsniveau,
|
||||
welche die meisten Programmierer je brauchen werden.
|
||||
Die Geschwindigkeit von C ist enorm, allerdings muss man sich stets der
|
||||
manuellen Speicherverwaltung bewusst sein.
|
||||
@ -22,7 +22,7 @@ manuellen Speicherverwaltung bewusst sein.
|
||||
> Standards:
|
||||
> `-Wall -Wextra -Werror -O2 -std=c99 -pedantic`
|
||||
>
|
||||
> Da gewisse Optionen (inbesondere der C-Standard) sehr stark vom Projekt
|
||||
> Da gewisse Optionen (insbesondere der C-Standard) sehr stark vom Projekt
|
||||
> abhängen, lohnt es sich, wenn die unterschiedlichen Optionen genauer
|
||||
> angeschaut werden. Eine Übersicht über die Compiler-Optionen findet man unter
|
||||
> [diesem](https://stackoverflow.com/questions/3375697/useful-gcc-flags-for-c) Stackoverflow-Beitrag.
|
||||
@ -64,12 +64,12 @@ enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT};
|
||||
// Funktionssignaturen werden entweder vorher in einer .h-Datei deklariert oder
|
||||
// am Anfang der .c-Datei.
|
||||
void function_1();
|
||||
int funkcion_2(void);
|
||||
int function_2(void);
|
||||
|
||||
// Es muss ein Funktionsprototyp deklariert werden vor der `main()` Funktion,
|
||||
// wenn die Funktion nach der `main()` Funktion gebraucht wird.
|
||||
int add_two_ints(int x1, int x2); // Funktionsprototyp
|
||||
// Auch wenn der Ausdrck `int add_two_ints(int, int)` auch valid wäre,
|
||||
// Auch wenn der Ausdruck `int add_two_ints(int, int)` auch valid wäre,
|
||||
// ist es empfohlen, dass man die Namen der Argumente hinschreibt für eine
|
||||
// einfachere Analyse.
|
||||
|
||||
@ -227,7 +227,7 @@ int main (int argc, char** argv) {
|
||||
// Wenn das Argument des `sizeof`-Operator ein Ausdruck ist, dann wird das
|
||||
// Argument nicht ausgewertet (außer Arrays mit variabler Länge)
|
||||
// Der Wert, der in diesem Fall zurückgegeben wird, ist eine Konstante zur
|
||||
// Kompillierzeit.
|
||||
// Kompilierzeit.
|
||||
|
||||
int a = 1;
|
||||
//size_t ist ein vorzeichenloser Integer Typ mit mindestens 2 Byte um die
|
||||
@ -283,7 +283,7 @@ int main (int argc, char** argv) {
|
||||
// repräsentiert. Wir müssen das Null-Byte nicht angeben in String-Literalen;
|
||||
// der Compiler fügt es am Ende des Array automatisch hinzu.
|
||||
char a_string[20] = "Das ist ein String";
|
||||
printf("%s\n", a_string); // %s formattiert einen String
|
||||
printf("%s\n", a_string); // %s formatiert einen String
|
||||
|
||||
printf("%d\n", a_string[18]); // => 0
|
||||
// Hier ist das Byte #19 0 (wie auch Byte #20)
|
||||
@ -394,7 +394,7 @@ int main (int argc, char** argv) {
|
||||
// aus der Header-Datei `<limits.h>` verwendet werden.
|
||||
|
||||
// Integer-Typen können zu Gleitkommazahlen und umgekehrt umgewandelt werden.
|
||||
printf("%f\n", (double) 100); // %f formattiert immer zu einem `double`...
|
||||
printf("%f\n", (double) 100); // %f formatiert immer zu einem `double`...
|
||||
printf("%f\n", (flaot) 100); // ... auch mit einem `float`
|
||||
printf("%d\n", (char)100.0);
|
||||
|
||||
@ -414,7 +414,7 @@ int main (int argc, char** argv) {
|
||||
int x = 0;
|
||||
printf("%p\n", (void *)&x); // verwende & um die Adresse der Variable
|
||||
// zu erhalten
|
||||
// %p formattiert einen Objektpointer des Typen void*)
|
||||
// %p formatiert einen Objektpointer des Typen void*)
|
||||
// => Gibt eine Adresse im Speicher aus
|
||||
|
||||
// Pointer starten mit einem * zu Beginn der Deklaration.
|
||||
@ -437,7 +437,7 @@ int main (int argc, char** argv) {
|
||||
printf("%d\n", *px); // => 1
|
||||
printf("%d\n", x); // => 1
|
||||
|
||||
// Arrays sind eine gute Möglichekit, einen zusammenhängenden Block von
|
||||
// Arrays sind eine gute Möglichkeit, einen zusammenhängenden Block von
|
||||
// Speicher zu allozieren.
|
||||
int x_array[20]; // deklariert einen Array der Größe 20 (Größe kann
|
||||
// nicht geändert werden.)
|
||||
@ -446,7 +446,7 @@ int main (int argc, char** argv) {
|
||||
x_array[xx] 20 -xx;
|
||||
} // Initialisiere x_array zu 20, 19, 18, ... 2, 1
|
||||
|
||||
// Deklariere ein Pointer des Typs int und initalisiere ihn, um auf `x_array`
|
||||
// Deklariere ein Pointer des Typs int und initialisiere ihn, um auf `x_array`
|
||||
// zu zeigen.
|
||||
int *x_ptr = x_array;
|
||||
// x_ptr zeigt jetzt auf den ersten Wert innerhalb des Arrays (int 20)
|
||||
@ -457,7 +457,7 @@ int main (int argc, char** argv) {
|
||||
// Ausnahme: Wenn das Array das Argument des Operators `&` ist.
|
||||
int arr[10];
|
||||
int (*ptr_to_arr)[10] = &arr; //`&arr` ist nicht vom Typ `int *`!
|
||||
// Es ist vom Typem "Pointer auf Array" (aus zehn `int`s)
|
||||
// Es ist vom Typen "Pointer auf Array" (aus zehn `int`s)
|
||||
// oder wenn das Array ein Stringliteral ist, welches gebraucht wird um ein
|
||||
// `char`-Array zu initialisieren.
|
||||
char other_arr[] = "foobarbazquirk";
|
||||
@ -631,7 +631,7 @@ void test_function() {
|
||||
// Variablen mit 0 initialisiert, wenn sie nicht mit einem anderen Startwert
|
||||
// initialisiert werden.
|
||||
// Es ist auch möglich, Funktionen als statisch zu deklarieren, damit diese
|
||||
// `private` sind. Privat heißt, dass sie nur in diesem Kontekt sichtbar sind.
|
||||
// `private` sind. Privat heißt, dass sie nur in diesem Kontext sichtbar sind.
|
||||
|
||||
|
||||
////////////////////////////////////////////////
|
||||
@ -707,12 +707,12 @@ void str_reverse_through_pointer(char *str_in) {
|
||||
// reduziert werden (ähnlich wie Arrays)
|
||||
(*f)(str_in); // Die Funktion einfach mit dem Pointer aufrufen
|
||||
// f(str_in); // Dies ist eine weitere gültige Alternative um eine Funktion
|
||||
// auzurufen.
|
||||
// aufzurufen.
|
||||
}
|
||||
|
||||
/*
|
||||
Solange die Signaturen der Funktionen übereinstimmen, kann man sämtliche Funktionen
|
||||
demselben Pointer zuweisen. Funktionspointer sind auf Grund der Einfacheit und
|
||||
demselben Pointer zuweisen. Funktionspointer sind auf Grund der Einfachheit und
|
||||
Leserlichkeit normalerweise wie folgt `typedef`d
|
||||
*/
|
||||
typedef void (*my_fnp_type)(char *);
|
||||
@ -722,7 +722,7 @@ typedef void (*my_fnp_type)(char *);
|
||||
|
||||
// Spezialzeichen
|
||||
// Im folgenden sin die englischen Begriffe jeweils in Klammern geschrieben,
|
||||
// da diese Begriffe auch im deutschten Sprachgebrauch verwendet werden.
|
||||
// da diese Begriffe auch im deutschen Sprachgebrauch verwendet werden.
|
||||
'\a'; // Alarmzeichen (alert (bell) character)
|
||||
'\n'; // Zeichen für neue Linie (newline character)
|
||||
'\t'; // Tab (tab character (left justifies text))
|
||||
@ -804,7 +804,7 @@ befindet wie die C-Quelldatei.
|
||||
#ifndef EXAMPLE_H /* Wenn EXAMPLE_H noch nicht definiert wurde */
|
||||
#define EXAMPLE_H /* definiere das Makro EXAMPLE_H */
|
||||
|
||||
// Es könenn weitere Header innerhalb eines Headers eingebunden werden, was dazu
|
||||
// Es können weitere Header innerhalb eines Headers eingebunden werden, was dazu
|
||||
// führt, dass diese bereits in anderen Dateien eingebunden wurden. So kann eine
|
||||
// Header-Datei in mehreren Dateien eingebunden werden. zum Beispiel:
|
||||
#include <string.h>
|
||||
@ -832,7 +832,7 @@ typedef struct Node {
|
||||
// Dies kann auch mit Aufzählungen gemacht werden.
|
||||
enum traffic_light_state {GREEN, YELLOW, RED};
|
||||
|
||||
// Funktionsprototypen könenn auch in Header-Dateien definiert werden, um die
|
||||
// Funktionsprototypen können auch in Header-Dateien definiert werden, um die
|
||||
// Funktion in unterschiedlichen Dateien zu verwenden, aber dies wird als schlechte
|
||||
// Praxis angesehen. Definitionen sollten in einer C-Datei erstellt werden.
|
||||
Node create_linked_list(int *value, int length);
|
||||
@ -844,6 +844,7 @@ Node create_linked_list(int *value, int length);
|
||||
|
||||
#endif /* Ende der Präprozessordirektive */
|
||||
```
|
||||
|
||||
## Weiterführende Literatur
|
||||
|
||||
Das Beste wird es sein, wenn man sich ein Exemplar des Buches
|
||||
|
422
de-de/clojure-de.html.markdown
Normal file
422
de-de/clojure-de.html.markdown
Normal file
@ -0,0 +1,422 @@
|
||||
---
|
||||
language: clojure
|
||||
filename: learnclojure-de.clj
|
||||
contributors:
|
||||
- ["Adam Bard", "http://adambard.com/"]
|
||||
translators:
|
||||
- ["Dennis Keller", "https://github.com/denniskeller"]
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Clojure ist ein Lispdialekt, der für die Java Virtual Maschine entwickelt worden ist. Sie hat eine stärkere Betonung auf reine [funktionale Programmierung](https://en.wikipedia.org/wiki/Functional_programming) als Common Lisp. Jedoch besitzt sie je nach Bedarf mehrere [STM](https://en.wikipedia.org/wiki/Software_transactional_memory) Werkzeuge zur Handhabung von Zustand.
|
||||
|
||||
Diese Verknüpfung erlaubt es, parallele Verarbeitung sehr einfach und häufig automatisch zu verarbeiten.
|
||||
|
||||
(Du brauchst die Clojure Version 1.2 oder neuer)
|
||||
|
||||
```clojure
|
||||
; Kommentare starten mit einem Semikolon.
|
||||
|
||||
; Clojure wird in "Forms" geschrieben, was nur Listen von Dingen
|
||||
; in Klammern sind, getrennt durch Leerzeichen.
|
||||
;
|
||||
; Der Clojure Leser nimmt an, dass das Erste, was aufgerufen wird
|
||||
; eine Funktion oder ein Makro ist, der Rest sind Argumente.
|
||||
|
||||
; Der erste Aufruf in einer Datei sollte ns sein, um den Namespace zu setzen.
|
||||
(ns learnclojure)
|
||||
|
||||
; Weitere einfache Beispiele:
|
||||
|
||||
; str erstellt einen String aus allen Argumenten
|
||||
(str "Hallo" " " "Welt") ; => "Hallo Welt"
|
||||
|
||||
; Mathe ist einfach
|
||||
(+ 1 1) ; => 2
|
||||
(- 2 1) ; => 1
|
||||
(* 1 2) ; => 2
|
||||
(/ 2 1) ; => 2
|
||||
|
||||
; Gleichheit ist =
|
||||
(= 1 1) ; => true
|
||||
(= 2 1) ; => false
|
||||
|
||||
; Du brauchst auch not für Logik
|
||||
(not true) ; => false
|
||||
|
||||
; Verschachtelte Forms funktionieren, wie erwartet
|
||||
(+ 1 (- 3 2)) ; = 1 + (3 - 2) => 2
|
||||
|
||||
; Typen
|
||||
;;;;;;;;;;;;;
|
||||
|
||||
; Clojure verwendet Javas Objekt Typen für Booleans, Strings und Zahlen.
|
||||
; Verwende `class` um sie zu inspizieren.
|
||||
(class 1) ; Integer-Literale sind standardmäßig java.lang.Long
|
||||
(class 1.); Float-Literale sind java.lang.Double
|
||||
(class ""); Strings sind immer in doppelten Anführungszeichen notiert und sind java.lang.String
|
||||
(class false) ; Booleans sind java.lang.Boolean
|
||||
(class nil); Der "null" Wert heißt nil
|
||||
|
||||
; Wenn du ein literale Liste aus Daten erzeugen willst, verwendest du ' um
|
||||
; zu verhindern dass es evaluiert wird
|
||||
'(+ 1 2) ; => (+ 1 2)
|
||||
; (Kurzform für (quote (+ 1 2)))
|
||||
|
||||
; Du kannst eine zitierte Liste evaluieren
|
||||
(eval '(+ 1 2)) ; => 3
|
||||
|
||||
; Kollektionen & Sequenzen
|
||||
;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Listen sind Linked-Lists Datenstrukturen, während Vektoren arraybasierend sind.
|
||||
; Vektoren und Listen sind auch Java Klassen!
|
||||
(class [1 2 3]); => clojure.lang.PersistentVector
|
||||
(class '(1 2 3)); => clojure.lang.PersistentList
|
||||
|
||||
; Eine Liste würde nur als (1 2 3) geschrieben, aber wir müssen es zitieren
|
||||
; damit der Leser aufhört zu denken, es sei eine Funktion.
|
||||
; Außerdem ist (list 1 2 3) dasselbe, wie '(1 2 3)
|
||||
|
||||
; "Kollektionen" sind nur Gruppen von Daten
|
||||
; Listen und Vektoren sind Kollektionen:
|
||||
(coll? '(1 2 3)) ; => true
|
||||
(coll? [1 2 3]) ; => true
|
||||
|
||||
; "Sequenzen" (seqs) sind abstrakte Beschreibungen von Listen von Daten.
|
||||
; Nur Listen sind seqs.
|
||||
(seq? '(1 2 3)) ; => true
|
||||
(seq? [1 2 3]) ; => false
|
||||
|
||||
; Ein seq muss nur einen Eintrittspunkt bereitstellen, wenn auf ihm zugegriffen wird.
|
||||
; Das heißt, dass seqs faul sein können -- Mit ihnen kann man unendliche Serien beschreiben.
|
||||
(range 4) ; => (0 1 2 3)
|
||||
(range) ; => (0 1 2 3 4 ...) (eine unendliche Serie)
|
||||
(take 4 (range)) ; (0 1 2 3)
|
||||
|
||||
; Verwende cons um ein Item zum Anfang einer Liste oder eines Vektors hinzuzufügen.
|
||||
(cons 4 [1 2 3]) ; => (4 1 2 3)
|
||||
(cons 4 '(1 2 3)) ; => (4 1 2 3)
|
||||
|
||||
; Conj fügt ein Item auf die effizienteste Weise zu einer Kollektion hinzu.
|
||||
; Für Listen fügt er sie an den Anfang hinzu. Für Vektoren fügt er sie an das Ende hinzu.
|
||||
(conj [1 2 3] 4) ; => [1 2 3 4]
|
||||
(conj '(1 2 3) 4) ; => (4 1 2 3)
|
||||
|
||||
; Verwende concat um Listen und Vektoren miteinander zu verbinden
|
||||
(concat [1 2] '(3 4)) ; => (1 2 3 4)
|
||||
|
||||
; Verwende filter, map um mit Kollektionen zu interagieren
|
||||
(map inc [1 2 3]) ; => (2 3 4)
|
||||
(filter even? [1 2 3]) ; => (2)
|
||||
|
||||
; Verwende reduce um sie zu reduzieren
|
||||
(reduce + [1 2 3 4])
|
||||
; = (+ (+ (+ 1 2) 3) 4)
|
||||
; => 10
|
||||
|
||||
; Reduce kann auch einen Initialwert als Argument verwenden
|
||||
(reduce conj [] '(3 2 1))
|
||||
; = (conj (conj (conj [] 3) 2) 1)
|
||||
; => [3 2 1]
|
||||
|
||||
; Funktionen
|
||||
;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Verwende fn um neue Funktionen zu erstellen. Eine Funktion gibt immer ihr
|
||||
; letztes Statement zurück.
|
||||
(fn [] "Hallo Welt") ; => fn
|
||||
|
||||
; (Du brauchst exta Klammern um sie aufzurufen)
|
||||
((fn [] "Hallo Welt")) ; => "Hallo Welt"
|
||||
|
||||
; Du kannst eine Variable mit def erstellen
|
||||
(def x 1)
|
||||
x ; => 1
|
||||
|
||||
; Weise eine Funktion einer Variable zu
|
||||
(def hello-world (fn [] "Hallo Welt"))
|
||||
(hello-world) ; => "Hallo Welt"
|
||||
|
||||
; Du kannst den Prozess verkürzen indem du defn verwendest
|
||||
(defn hello-world [] "Hallo Welt")
|
||||
|
||||
; [] ist die Liste der Argumente für die Funktion
|
||||
; The [] is the list of arguments for the function.
|
||||
(defn hello [name]
|
||||
(str "Hallo " name))
|
||||
(hello "Steve") ; => "Hallo Steve"
|
||||
|
||||
; Du kannst diese Kurzschreibweise verwenden um Funktionen zu erstellen:
|
||||
(def hello2 #(str "Hallo " %1))
|
||||
(hello2 "Julie") ; => "Hallo Julie"
|
||||
|
||||
; Du kannst auch multi-variadische Funktionen haben
|
||||
(defn hello3
|
||||
([] "Hallo Welt")
|
||||
([name] (str "Hallo " name)))
|
||||
(hello3 "Jake") ; => "Hallo Jake"
|
||||
(hello3) ; => "Hallo Welt"
|
||||
|
||||
; Funktionen können auch extra Argumente in einem seq für dich speichern
|
||||
(defn count-args [& args]
|
||||
(str "Du hast " (count args) " Argumente übergeben: " args))
|
||||
(count-args 1 2 3) ; => "Du hast 3 Argumente übergeben: (1 2 3)"
|
||||
|
||||
; Du kannst reguläre und gepackte Argumente mischen
|
||||
(defn hello-count [name & args]
|
||||
(str "Hallo " name ", Du hast " (count args) " extra Argumente übergeben"))
|
||||
(hello-count "Finn" 1 2 3)
|
||||
; => "Hallo Finn, Du hast 3 extra Argumente übergeben"
|
||||
|
||||
|
||||
; Maps
|
||||
;;;;;;;;;;
|
||||
|
||||
; Hash maps und Array maps teilen sich ein Interface. Hash maps haben eine schnellere Zugriffszeit,
|
||||
; aber behalten keine Schlüsselreihenfolge.
|
||||
(class {:a 1 :b 2 :c 3}) ; => clojure.lang.PersistentArrayMap
|
||||
(class (hash-map :a 1 :b 2 :c 3)) ; => clojure.lang.PersistentHashMap
|
||||
|
||||
; Arraymaps werden durch die meisten Operationen automatisch zu Hashmaps,
|
||||
; sobald sie groß genug werden. Das heißt du musst dich nicht darum sorgen.
|
||||
|
||||
; Maps können einen beliebigen Hash-Typ als Schlüssel verwenden, in der Regel
|
||||
; sind jedoch Keywords am besten. Keywords sind wie Strings, jedoch besitzen sie
|
||||
; Performance-Vorteile
|
||||
(class :a) ; => clojure.lang.Keyword
|
||||
|
||||
(def stringmap {"a" 1, "b" 2, "c" 3})
|
||||
stringmap ; => {"a" 1, "b" 2, "c" 3}
|
||||
|
||||
(def keymap {:a 1, :b 2, :c 3})
|
||||
keymap ; => {:a 1, :c 3, :b 2}
|
||||
|
||||
; Übrigens werden Kommas als Leerzeichen behandelt und machen nichts.
|
||||
|
||||
; Rufe einen Wert von einer Map ab, indem du sie als Funktion aufrufst
|
||||
(stringmap "a") ; => 1
|
||||
(keymap :a) ; => 1
|
||||
|
||||
; Keywords können auch verwendet werden um ihren Wert aus der Map zu bekommen!
|
||||
(:b keymap) ; => 2
|
||||
|
||||
; Versuche es nicht mit Strings.
|
||||
;("a" stringmap)
|
||||
; => Exception: java.lang.String cannot be cast to clojure.lang.IFn
|
||||
|
||||
; Das Abrufen eines nicht vorhandenen Keys gibt nil zurück
|
||||
(stringmap "d") ; => nil
|
||||
|
||||
; Verwende assoc um einen neuen Key zu einer Hash-map hinzuzufügen
|
||||
(def newkeymap (assoc keymap :d 4))
|
||||
newkeymap ; => {:a 1, :b 2, :c 3, :d 4}
|
||||
|
||||
; Aber denk daran, Clojure Typen sind unveränderlich!
|
||||
keymap ; => {:a 1, :b 2, :c 3}
|
||||
|
||||
; Verwende dissoc um Keys zu entfernen
|
||||
(dissoc keymap :a :b) ; => {:c 3}
|
||||
|
||||
; Sets
|
||||
;;;;;;
|
||||
|
||||
(class #{1 2 3}) ; => clojure.lang.PersistentHashSet
|
||||
(set [1 2 3 1 2 3 3 2 1 3 2 1]) ; => #{1 2 3}
|
||||
|
||||
; Füge ein Element mit conj hinzu
|
||||
(conj #{1 2 3} 4) ; => #{1 2 3 4}
|
||||
|
||||
; Entferne ein Element mit disj
|
||||
(disj #{1 2 3} 1) ; => #{2 3}
|
||||
|
||||
; Teste auf Existenz, indem du das Set als Funktion verwendest:
|
||||
(#{1 2 3} 1) ; => 1
|
||||
(#{1 2 3} 4) ; => nil
|
||||
|
||||
; Es gibt mehr Funktionen in dem clojure.sets Namespace.
|
||||
|
||||
; Nützliche Forms
|
||||
;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Logische Konstrukte in Clojure sind nur Makros und sie sehen, wie alles
|
||||
; andere aus
|
||||
(if false "a" "b") ; => "b"
|
||||
(if false "a") ; => nil
|
||||
|
||||
; Verwende let um temporäre Bindungen aufzubauen
|
||||
(let [a 1 b 2]
|
||||
(> a b)) ; => false
|
||||
|
||||
; Gruppiere Statements mit do zusammen
|
||||
; Group statements together with do
|
||||
(do
|
||||
(print "Hallo")
|
||||
"Welt") ; => "Welt" (prints "Hallo")
|
||||
|
||||
; Funktionen haben ein implizites do
|
||||
(defn print-and-say-hello [name]
|
||||
(print "Sage Hallo zu " name)
|
||||
(str "Hallo " name))
|
||||
(print-and-say-hello "Jeff") ;=> "Hallo Jeff" (prints "Sage Hallo zu Jeff")
|
||||
|
||||
; let macht das auch
|
||||
(let [name "Urkel"]
|
||||
(print "Sage Hallo zu " name)
|
||||
(str "Hallo " name)) ; => "Hallo Urkel" (prints "Sage Hallo zu Urkel")
|
||||
|
||||
|
||||
; Verwende die Threading Makros (-> and ->>) um Transformationen von
|
||||
; Daten deutlicher auszudrücken.
|
||||
|
||||
; Das "Thread-zuerst" Makro (->) fügt in jede Form das Ergebnis des
|
||||
; Vorherigen als erstes Argument (zweites Element) ein.
|
||||
(->
|
||||
{:a 1 :b 2}
|
||||
(assoc :c 3) ;=> (assoc {:a 1 :b 2} :c 3)
|
||||
(dissoc :b)) ;=> (dissoc (assoc {:a 1 :b 2} :c 3) :b)
|
||||
|
||||
; Dieser Ausdruck kann auch als so geschrieben werden:
|
||||
; (dissoc (assoc {:a 1 :b 2} :c 3) :b)
|
||||
; and evaluates to {:a 1 :c 3}
|
||||
|
||||
; Der Doppelpfeil macht das Selbe, aber er fügt das Ergebnis von jeder
|
||||
; Zeile an das Ende der Form, Das ist vor allem für Operationen auf
|
||||
; Kollektionen nützlich:
|
||||
(->>
|
||||
(range 10)
|
||||
(map inc) ;=> (map inc (range 10)
|
||||
(filter odd?) ;=> (filter odd? (map inc (range 10))
|
||||
(into [])) ;=> (into [] (filter odd? (map inc (range 10)))
|
||||
; Result: [1 3 5 7 9]
|
||||
|
||||
; Wenn du in einer Situation bist, in der du mehr Freiheit willst,
|
||||
; wohin du das Ergebnis vorheriger Datentransformationen in einem Ausdruck
|
||||
; platzieren möchtest, kannst du das as-> Macro verwenden. Mit diesem Macro
|
||||
; kannst du einen speziellen Namen auf die Ausgabe einer Transformationen geben.
|
||||
; Du kannst es als Platzhalter in verketteten Ausdrücken verwenden:
|
||||
|
||||
(as-> [1 2 3] input
|
||||
(map inc input);=> Du kannst die letzte Ausgabe der Transformation in der letzten Position verwenden
|
||||
(nth input 2) ;=> und auch in der zweiten Position, im selben Ausdruck verwenden
|
||||
(conj [4 5 6] input [8 9 10])) ;=> oder auch in der Mitte!
|
||||
|
||||
|
||||
|
||||
; Module
|
||||
;;;;;;;;;;;;;;;
|
||||
|
||||
; Verwende "use" um alle Funktionen aus einem Modul zu bekommen
|
||||
(use 'clojure.set)
|
||||
|
||||
; Nun können wir set Operationen verwenden
|
||||
(intersection #{1 2 3} #{2 3 4}) ; => #{2 3}
|
||||
(difference #{1 2 3} #{2 3 4}) ; => #{1}
|
||||
|
||||
; Du kannst auch auswählen nur ein Subset von Funktionen zu importieren
|
||||
(use '[clojure.set :only [intersection]])
|
||||
|
||||
; Verwende require um ein Modul zu importieren
|
||||
(require 'clojure.string)
|
||||
|
||||
; Verwende / um eine Funktion aus einem Modul aufzurufen
|
||||
; Hier verwenden wir das Modul clojure.string und die Funktion blank?
|
||||
(clojure.string/blank? "") ; => true
|
||||
|
||||
; Du kannst auch einem Modul einen kürzeren Namen beim Import geben
|
||||
(require '[clojure.string :as str])
|
||||
(str/replace "Das ist ein Test." #"[a-o]" str/upper-case) ; => "DAs IsT EIN TEsT."
|
||||
; (#"" bezeichnet einen regulären literalen Ausdruck)
|
||||
|
||||
; Du kannst require aus einem Namespace verwenden (auch use ist möglich, aber nicht zu empfehlen)
|
||||
; indem du :require verwendest.
|
||||
; Du brauchst keine Zitierzeichen für deine Module verwenden, wenn du
|
||||
; es auf diese Weise machst.
|
||||
(ns test
|
||||
(:require
|
||||
[clojure.string :as str]
|
||||
[clojure.set :as set]))
|
||||
|
||||
; Java
|
||||
;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Java hat eine riesige und nützliche Standardbibliothek,
|
||||
; du möchtest lernen wie man sie verwendet.
|
||||
|
||||
; Verwende import um ein Java modul zu laden.
|
||||
(import java.util.Date)
|
||||
|
||||
; Du kannst auch von einem ns importieren.
|
||||
(ns test
|
||||
(:import java.util.Date
|
||||
java.util.Calendar))
|
||||
|
||||
; Verwende den Klassennamen mit einem "." am Ende, um eine neue Instanz zu erstellen
|
||||
(Date.) ; <a date object>
|
||||
|
||||
; Verwende . um Methoden aufzurufen oder verwende die ".method" Abkürzung
|
||||
(. (Date.) getTime) ; <a timestamp>
|
||||
(.getTime (Date.)) ; Genau das Selbe
|
||||
|
||||
; Verwende / um statische Methoden aufzurufen
|
||||
(System/currentTimeMillis) ; <a timestamp> (system ist immer da)
|
||||
|
||||
; Verwende doto um mit veränderliche Klassen besser umzugehen
|
||||
(import java.util.Calendar)
|
||||
(doto (Calendar/getInstance)
|
||||
(.set 2000 1 1 0 0 0)
|
||||
.getTime) ; => A Date. set to 2000-01-01 00:00:00
|
||||
|
||||
; STM
|
||||
;;;;;;;;;;;;;;;;;
|
||||
|
||||
; Software Transactional Memory ist der Mechanismus, den Clojure verwendet
|
||||
; um mit persistenten Zuständen umzugehen. Es gibt ein Paar Konstrukte in
|
||||
; Clojure die es verwenden.
|
||||
|
||||
; Ein Atom ist das Einfachste. Gebe es einen Initialwert
|
||||
(def my-atom (atom {}))
|
||||
|
||||
; Update ein Atom mit swap!.
|
||||
; swap! nimmt eine Funktion und ruft sie mit dem aktuellen Zustand des
|
||||
; Atoms auf und alle nachfolgenden Argumente als das Zweite
|
||||
(swap! my-atom assoc :a 1) ; Setzt my-atom zu dem Ergebnis von (assoc {} :a 1)
|
||||
(swap! my-atom assoc :b 2) ; Setzt my-atom zu dem Ergebnis von (assoc {:a 1} :b 2)
|
||||
|
||||
; Verwende '@' um das Atom zu dereferenzieren und den Wert zu bekommen
|
||||
my-atom ;=> Atom<#...> (Gibt das Atom Objekt zurück
|
||||
@my-atom ; => {:a 1 :b 2}
|
||||
|
||||
; Hier ist ein einfacher Zähler mit einem Atom
|
||||
(def counter (atom 0))
|
||||
(defn inc-counter []
|
||||
(swap! counter inc))
|
||||
|
||||
(inc-counter)
|
||||
(inc-counter)
|
||||
(inc-counter)
|
||||
(inc-counter)
|
||||
(inc-counter)
|
||||
|
||||
@counter ; => 5
|
||||
|
||||
; Andere STM Konstrukte sind refs und agents.
|
||||
; Refs: http://clojure.org/refs
|
||||
; Agents: http://clojure.org/agents
|
||||
```
|
||||
|
||||
### Weiterführende Literatur
|
||||
|
||||
Das ist alles andere als erschöpfend, aber hoffentlich ist es genug, um dich auf die Beine zu stellen.
|
||||
|
||||
Clojure.org hat eine Menge von Artikeln:
|
||||
[http://clojure.org/](http://clojure.org/)
|
||||
|
||||
Clojuredocs.org hat eine Dokumentation mit Beispielen für die meisten Kernfunktionen
|
||||
[http://clojuredocs.org/quickref/Clojure%20Core](http://clojuredocs.org/quickref/Clojure%20Core)
|
||||
|
||||
4Clojure ist eine gute Möglichkeit um deine clojure/FP zu verbessern:
|
||||
[http://www.4clojure.com/](http://www.4clojure.com/)
|
||||
|
||||
Clojure-doc.org (ja, wirklich) hat eine Reihe von Artikeln zum Starten:
|
||||
[http://clojure-doc.org/](http://clojure-doc.org/)
|
@ -11,11 +11,11 @@ lang: de-de
|
||||
Wie mit allen Lisps besitzt auch Clojure die inhärente [Homoikonizität](https://en.wikipedia.org/wiki/Homoiconic),
|
||||
die dir den vollen Zugang der Sprache gibt, um
|
||||
Code-Generierungsroutinen zu schreiben. Diese werden "Macros" genannt.
|
||||
Macros geben dir eine leistungsarke Möglichkeit, die Sprache
|
||||
Macros geben dir eine leistungsstarke Möglichkeit, die Sprache
|
||||
an deine Bedürfnisse anzupassen.
|
||||
|
||||
Sei aber vorsichtig, es wird als schlechter Stil angesehen, wenn du
|
||||
ein Macro schreibst, obwohl eine Funktion genausogut funktionieren würde.
|
||||
ein Macro schreibst, obwohl eine Funktion genauso gut funktionieren würde.
|
||||
Verwende nur dann ein Macro, wenn du Kontrolle darüber brauchst, wann oder ob Argumente in einer Form evaluiert werden.
|
||||
|
||||
Wenn du mit Clojure vertraut sein möchtest, stelle sicher, dass du alles in [Clojure in Y Minutes](/docs/clojure/) verstehst.
|
||||
@ -59,7 +59,7 @@ Wenn du mit Clojure vertraut sein möchtest, stelle sicher, dass du alles in [Cl
|
||||
|
||||
;; Aber wenn du versuchst das mit einer zitierten Liste zu machen wirst du
|
||||
;; einen Fehler bekommen, weil das Argument auch zitiert sein wird.
|
||||
;; Um dies zu umgehen, bietet Clojure einee Art und Weise Macros zu zitieren: `
|
||||
;; Um dies zu umgehen, bietet Clojure eine Art und Weise Macros zu zitieren: `
|
||||
;; In ` kannst du ~ verwenden um in den äußeren Bereich zu kommen.
|
||||
(defmacro inc2-quoted [arg]
|
||||
`(+ 2 ~arg))
|
||||
@ -156,6 +156,6 @@ Wenn du mit Clojure vertraut sein möchtest, stelle sicher, dass du alles in [Cl
|
||||
|
||||
[Macros schreiben](http://www.braveclojure.com/writing-macros/)
|
||||
|
||||
[Offiziele Docs](http://clojure.org/macros)
|
||||
[Offizielle Docs](http://clojure.org/macros)
|
||||
|
||||
[Wann verwendet man Macros?](https://lispcast.com/when-to-use-a-macro/)
|
||||
|
@ -10,7 +10,6 @@ lang: de-de
|
||||
---
|
||||
|
||||
```crystal
|
||||
|
||||
# Das ist ein Kommentar
|
||||
|
||||
# Alles ist ein Objekt
|
||||
@ -83,7 +82,7 @@ true.class # => Bool
|
||||
"s".class # => String
|
||||
|
||||
# Strings sind unveränderlich
|
||||
s = 'hello, " # => "hello, " : String
|
||||
s = "hello, " # => "hello, " : String
|
||||
s.object_id # => 1234667712 : UInt64
|
||||
s += "Crystal" # => "hello, Crystal" : String
|
||||
s.object_id # => 142528472 : UInt64
|
||||
@ -171,7 +170,7 @@ set << 3
|
||||
{1 => 2, 3 => 4}.class # => Hash(Int32, Int32)
|
||||
{1 => 2, 'a' => 3}.class # => Hash (Int32 | Char, Int32)
|
||||
|
||||
# Leere Hashes sollten einen Typen spezifieren
|
||||
# Leere Hashes sollten einen Typen spezifizieren
|
||||
{} # Syntaxfehler
|
||||
{} of Int32 => Int32 # {}
|
||||
Hash(Int32, Int32).new # {}
|
||||
@ -446,7 +445,7 @@ class Human
|
||||
end
|
||||
|
||||
|
||||
# Eine Klasse instanzieren
|
||||
# Eine Klasse instanziieren
|
||||
jim = Human.new("Jim Halpert")
|
||||
|
||||
dwight = Human.new("Dwight K. Schrute")
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -139,12 +139,11 @@ selector {
|
||||
|
||||
/* Schriften */
|
||||
font-family: Arial;
|
||||
font-family: "Courier New"; /* wenn der Name ein Leerzeichen beinhält, kommt er in
|
||||
font-family: "Courier New"; /* wenn der Name ein Leerzeichen enthält, kommt er in
|
||||
Anführungszeichen */
|
||||
font-family: "Courier New", Trebuchet, Arial; /* wird die erste Schriftart
|
||||
nicht gefunden, wird die zweite benutzt, usw. */
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## Benutzung
|
||||
@ -164,7 +163,6 @@ empfohlen ist -->
|
||||
<!-- Oder direkt auf einem Element (sollte aber vermieden werden) -->
|
||||
<div style='property:value;'>
|
||||
</div>
|
||||
|
||||
```
|
||||
|
||||
## Spezifität
|
||||
@ -190,7 +188,6 @@ p {}
|
||||
|
||||
/*E*/
|
||||
p { property: wert !important; }
|
||||
|
||||
```
|
||||
|
||||
und das folgende Markup:
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
language: D
|
||||
filename: learnd-de.d
|
||||
language: D
|
||||
filename: learnd-de.d
|
||||
contributors:
|
||||
- ["Nick Papanastasiou", "www.nickpapanastasiou.github.io"]
|
||||
translators:
|
||||
@ -8,13 +8,13 @@ translators:
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
```c
|
||||
```d
|
||||
// Es war klar, dass das kommt...
|
||||
module hello;
|
||||
|
||||
import std.stdio;
|
||||
|
||||
// argumente sind optional
|
||||
// Argumente sind optional
|
||||
void main(string[] args) {
|
||||
writeln("Hello, World!");
|
||||
}
|
||||
@ -22,13 +22,13 @@ void main(string[] args) {
|
||||
|
||||
Wenn du so wie ich bist und viel Zeit im Internet verbringst, stehen die Chancen
|
||||
gut, dass du schonmal über [D](http://dlang.org/) gehört hast.
|
||||
Die D-Sprache ist eine moderne, überall einsetzbare programmiersprache die von
|
||||
Die D-Sprache ist eine moderne, überall einsetzbare Programmiersprache die von
|
||||
Low bis High Level verwendet werden kann und dabei viele Stile anbietet.
|
||||
|
||||
D wird aktiv von Walter Bright und Andrei Alexandrescu entwickelt, zwei super schlaue,
|
||||
richtig coole leute. Da das jetzt alles aus dem Weg ist - auf zu den Beispielen!
|
||||
richtig coole Leute. Da das jetzt alles aus dem Weg ist - auf zu den Beispielen!
|
||||
|
||||
```c
|
||||
```d
|
||||
import std.stdio;
|
||||
|
||||
void main() {
|
||||
@ -39,8 +39,8 @@ void main() {
|
||||
}
|
||||
|
||||
auto n = 1; // auto um den Typ vom Compiler bestimmen zu lassen
|
||||
|
||||
// Zahlenliterale können _ verwenden für lesbarkeit
|
||||
|
||||
// Zahlenliterale können _ verwenden für Lesbarkeit
|
||||
while(n < 10_000) {
|
||||
n += n;
|
||||
}
|
||||
@ -69,11 +69,11 @@ void main() {
|
||||
```
|
||||
|
||||
Neue Typen können mit `struct`, `class`, `union`, und `enum` definiert werden.
|
||||
Structs und unions werden as-value (koppiert) an Methoden übergeben wogegen
|
||||
Structs und unions werden as-value (kopiert) an Methoden übergeben wogegen
|
||||
Klassen als Referenz übergeben werden. Templates können verwendet werden um
|
||||
alle Typen zu parameterisieren.
|
||||
alle Typen zu parametrisieren.
|
||||
|
||||
```c
|
||||
```d
|
||||
// Hier, T ist ein Type-Parameter, Er funktioniert wie Generics in C#/Java/C++
|
||||
struct LinkedList(T) {
|
||||
T data = null;
|
||||
@ -82,7 +82,7 @@ struct LinkedList(T) {
|
||||
|
||||
class BinTree(T) {
|
||||
T data = null;
|
||||
|
||||
|
||||
// Wenn es nur einen T Parameter gibt, können die Klammern um ihn weggelassen werden
|
||||
BinTree!T left;
|
||||
BinTree!T right;
|
||||
@ -121,22 +121,21 @@ void swap(T)(ref T a, ref T b) {
|
||||
b = temp;
|
||||
}
|
||||
|
||||
// Templates können ebenso Werte parameterisieren.
|
||||
// Templates können ebenso Werte parametrisieren.
|
||||
class Matrix(uint m, uint n, T = int) {
|
||||
T[m] rows;
|
||||
T[n] columns;
|
||||
}
|
||||
|
||||
auto mat = new Matrix!(3, 3); // Standardmäßig ist T vom Typ Integer
|
||||
|
||||
```
|
||||
|
||||
Wo wir schon bei Klassen sind - Wie wäre es mit Properties! Eine Property
|
||||
ist eine Funktion, die wie ein Wert agiert. Das gibt uns viel klarere Syntax
|
||||
im Stil von `structure.x = 7` was gleichgültig wäre zu `structure.setX(7)`
|
||||
|
||||
```c
|
||||
// Diese Klasse ist parameterisiert mit T, U
|
||||
```d
|
||||
// Diese Klasse ist parametrisiert mit T, U
|
||||
|
||||
class MyClass(T, U) {
|
||||
T _data;
|
||||
@ -148,13 +147,13 @@ class MyClass(T, U) {
|
||||
class MyClass(T, U) {
|
||||
T _data;
|
||||
U _other;
|
||||
|
||||
|
||||
// Konstruktoren heißen immer `this`
|
||||
this(T t, U u) {
|
||||
data = t;
|
||||
other = u;
|
||||
}
|
||||
|
||||
|
||||
// getters
|
||||
@property T data() {
|
||||
return _data;
|
||||
@ -164,8 +163,8 @@ class MyClass(T, U) {
|
||||
return _other;
|
||||
}
|
||||
|
||||
// setters
|
||||
// @property kann genauso gut am ende der Methodensignatur stehen
|
||||
// setters
|
||||
// @property kann genauso gut am ende der Methodensignatur stehen
|
||||
void data(T t) @property {
|
||||
_data = t;
|
||||
}
|
||||
@ -181,13 +180,13 @@ void main() {
|
||||
|
||||
mc.data = 7;
|
||||
mc.other = "seven";
|
||||
|
||||
|
||||
writeln(mc.data);
|
||||
writeln(mc.other);
|
||||
}
|
||||
```
|
||||
|
||||
Mit properties können wir sehr viel logik hinter unseren gettern
|
||||
Mit properties können wir sehr viel Logik hinter unseren gettern
|
||||
und settern hinter einer schönen Syntax verstecken
|
||||
|
||||
Andere Objektorientierte features sind beispielsweise
|
||||
@ -202,17 +201,17 @@ puren Funktionen und unveränderbaren Daten.
|
||||
Zusätzlich können viele funktionale Algorithmen wie z.B
|
||||
map, filter, reduce und friends im `std.algorithm` Modul gefunden werden!
|
||||
|
||||
```c
|
||||
```d
|
||||
import std.algorithm : map, filter, reduce;
|
||||
import std.range : iota; // builds an end-exclusive range
|
||||
|
||||
void main() {
|
||||
// Wir wollen die Summe aller Quadratzahlen zwischen
|
||||
// 1 und 100 ausgeben. Nichts leichter als das!
|
||||
|
||||
|
||||
// Einfach eine Lambda-Funktion als Template Parameter übergeben
|
||||
// Es ist genau so gut möglich eine normale Funktion hier zu übergeben
|
||||
// Lambdas bieten sich hier aber an.
|
||||
// Lambdas bieten sich hier aber an.
|
||||
auto num = iota(1, 101).filter!(x => x % 2 == 0)
|
||||
.map!(y => y ^^ 2)
|
||||
.reduce!((a, b) => a + b);
|
||||
@ -225,21 +224,21 @@ Ist dir aufgefallen, wie wir eine Haskell-Style Pipeline gebaut haben
|
||||
um num zu berechnen?
|
||||
Das war möglich durch die Uniform Function Call Syntax.
|
||||
Mit UFCS können wir auswählen, ob wir eine Funktion als Methode oder
|
||||
als freie Funktion aufrufen. Walters artikel dazu findet ihr
|
||||
[hier.](http://www.drdobbs.com/cpp/uniform-function-call-syntax/232700394)
|
||||
als freie Funktion aufrufen. Walters Artikel dazu findet ihr
|
||||
[hier.](http://www.drdobbs.com/cpp/uniform-function-call-syntax/232700394)
|
||||
Kurzgesagt kann man Funktionen, deren erster Parameter vom typ A ist, als
|
||||
Methode auf A anwenden.
|
||||
|
||||
Parrallel Computing ist eine Tolle sache, findest du nicht auch?
|
||||
Parallel Computing ist eine tolle Sache, findest du nicht auch?
|
||||
|
||||
```c
|
||||
```d
|
||||
import std.stdio;
|
||||
import std.parallelism : parallel;
|
||||
import std.math : sqrt;
|
||||
|
||||
void main() {
|
||||
// Wir wollen die Wurzel von jeder Zahl in unserem Array berechnen
|
||||
// und dabei alle Kerne verwenden, die wir zur verfügung haben
|
||||
// und dabei alle Kerne verwenden, die wir zur Verfügung haben
|
||||
auto arr = new double[1_000_000];
|
||||
|
||||
// Wir verwenden den Index und das Element als Referenz
|
||||
@ -248,5 +247,4 @@ void main() {
|
||||
ref = sqrt(i + 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
@ -288,7 +288,7 @@ let false : Bool = Prelude.Bool.not True
|
||||
-- importiert und nicht als Dhall-Code interpretiert.
|
||||
let sourceCode : Text = https://prelude.dhall-lang.org/Bool/not as Text
|
||||
|
||||
-- Environment-Variablen können auch imortiert werden.
|
||||
-- Environment-Variablen können auch importiert werden.
|
||||
let presentWorkingDirectory = env:PWD as Text
|
||||
|
||||
-- Mit `?` kann man eine “Fallback-Expression” angeben, für den Fall
|
||||
|
@ -40,13 +40,13 @@ Dies wird als Dynamische Programmierung bezeichnet.
|
||||
Das Problem mit der längsten ansteigenden Subsequenz besteht darin,
|
||||
die längste ansteigende Subsequenz einer gegebenen Sequenz zu finden.
|
||||
Gegeben die Sequenz `S= {a1, a2, a3, a3, a4,..............., an-1, an }`,
|
||||
müssen wir die größte Teilmenge finden, so daß für alle `j` und `i`, `j<i`
|
||||
müssen wir die größte Teilmenge finden, sodass für alle `j` und `i`, `j<i`
|
||||
in der Teilmenge `aj<ai` gilt.
|
||||
Zuerst müssen wir bei jedem Index i den Wert der längsten Subsequenzen (LSi)
|
||||
finden, wobei das letzte Element der Sequenz ai ist. Dann wäre die größte LSi
|
||||
die längste Subsequenz in der gegebenen Sequenz. Am Anfang wird der LSi mit
|
||||
eins belegt, da ai ein Element der Sequenz (Letztes Element) ist.
|
||||
Dann ist für alle `j` mit `j<i` und `aj<ai`, so dass wir den größten LSj finden
|
||||
Dann ist für alle `j` mit `j<i` und `aj<ai`, sodass wir den größten LSj finden
|
||||
und zum LSi hinzufügen. Der Algorithmus hat eine Laufzeit von *O(n2)*.
|
||||
|
||||
Pseudocode zur Bestimmung der Länge der am längsten ansteigenden Subsequenz:
|
||||
@ -56,6 +56,7 @@ wie `largest_sequences_so_far` und dessen Index würde eine Menge Zeit sparen.
|
||||
|
||||
Ein ähnliches Konzept könnte auch bei der Suche nach dem längsten Weg
|
||||
in gerichteten azyklischen Graphen angewandt werden.
|
||||
|
||||
```python
|
||||
for i=0 to n-1
|
||||
LS[i]=1
|
||||
|
@ -82,7 +82,7 @@ false
|
||||
;;; markierte Elemente ;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
; EDN kann erweitert werden, indem Elemente mit # Symbolen makiert werden.
|
||||
; EDN kann erweitert werden, indem Elemente mit # Symbolen markiert werden.
|
||||
|
||||
#MyYelpClone/MenuItem {:name "eggs-benedict" :rating 10}
|
||||
|
||||
@ -102,11 +102,10 @@ false
|
||||
(edn/read-string {:readers {'MyYelpClone/MenuItem map->menu-item}}
|
||||
"#MyYelpClone/MenuItem {:name \"eggs-benedict\" :rating 10}")
|
||||
; -> #user.MenuItem{:name "eggs-benedict", :rating 10}
|
||||
|
||||
```
|
||||
|
||||
# Referenzen
|
||||
|
||||
- [EDN spec](https://github.com/edn-format/edn)
|
||||
- [Implementationen](https://github.com/edn-format/edn/wiki/Implementations)
|
||||
- [makierte Elemente](http://www.compoundtheory.com/clojure-edn-walkthrough/)
|
||||
- [markierte Elemente](http://www.compoundtheory.com/clojure-edn-walkthrough/)
|
||||
|
@ -1,423 +1,421 @@
|
||||
---
|
||||
language: elixir
|
||||
contributors:
|
||||
- ["Joao Marques", "http://github.com/mrshankly"]
|
||||
translators:
|
||||
- ["Gregor Große-Bölting", "http://www.ideen-und-soehne.de"]
|
||||
filename: learnelixir-de.ex
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Elixir ist eine moderne, funktionale Sprache für die Erlang VM. Sie ist voll
|
||||
kompatibel mit Erlang, verfügt aber über eine freundlichere Syntax und bringt
|
||||
viele Features mit.
|
||||
|
||||
```ruby
|
||||
|
||||
# Einzeilige Kommentare werden mit der Raute gesetzt.
|
||||
|
||||
# Es gibt keine mehrzeiligen Kommentare;
|
||||
# es ist aber problemlos möglich mehrere einzeilige Kommentare hintereinander
|
||||
# zu setzen (so wie hier).
|
||||
|
||||
# Mit 'iex' ruft man die Elixir-Shell auf.
|
||||
# Zum kompilieren von Modulen dient der Befehl 'elixirc'.
|
||||
|
||||
# Beide Befehle sollten als Umgebungsvariable gesetzt sein, wenn Elixir korrekt
|
||||
# installiert wurde.
|
||||
|
||||
## ---------------------------
|
||||
## -- Basistypen
|
||||
## ---------------------------
|
||||
|
||||
# Es gibt Nummern:
|
||||
3 # Integer
|
||||
0x1F # Integer
|
||||
3.0 # Float
|
||||
|
||||
# Für bessere Lesbarkeit des Codes können Unterstriche "_" als Trennzeichen verwendet werden
|
||||
1_000_000 == 1000000 # Integer
|
||||
1_000.567 == 1000.567 # Float
|
||||
|
||||
# Atome, das sind Literale, sind Konstanten mit Namen. Sie starten mit einem
|
||||
# ':'.
|
||||
:hello # Atom
|
||||
|
||||
# Außerdem gibt es Tupel, deren Werte im Arbeitsspeicher vorgehalten werden.
|
||||
{1,2,3} # Tupel
|
||||
|
||||
# Die Werte innerhalb eines Tupels können mit der 'elem'-Funktion ausgelesen
|
||||
# werden:
|
||||
elem({1, 2, 3}, 0) # => 1
|
||||
|
||||
# Listen sind als verkettete Listen implementiert.
|
||||
[1, 2, 3] # list
|
||||
|
||||
# Auf Kopf und Rest einer Liste kann wie folgt zugegriffen werden:
|
||||
[ kopf | rest ] = [1,2,3]
|
||||
kopf # => 1
|
||||
rest # => [2, 3]
|
||||
|
||||
# In Elixir, wie auch in Erlang, kennzeichnet '=' ein 'pattern matching'
|
||||
# (Musterabgleich) und keine Zuweisung.
|
||||
# Das heißt, dass die linke Seite auf die rechte Seite 'abgeglichen' wird.
|
||||
# Auf diese Weise kann im Beispiel oben auf Kopf und Rest der Liste zugegriffen
|
||||
# werden.
|
||||
|
||||
# Ein Musterabgleich wird einen Fehler werfen, wenn die beiden Seiten nicht
|
||||
# zusammenpassen.
|
||||
# Im folgenden Beispiel haben die Tupel eine unterschiedliche Anzahl an
|
||||
# Elementen:
|
||||
{a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
|
||||
|
||||
# Es gibt außerdem 'binaries',
|
||||
<<1,2,3>> # binary.
|
||||
|
||||
# Strings und 'char lists'
|
||||
"hello" # String
|
||||
'hello' # Char-Liste
|
||||
|
||||
# ... und mehrzeilige Strings
|
||||
"""
|
||||
Ich bin ein
|
||||
mehrzeiliger String.
|
||||
"""
|
||||
#=> "Ich bin ein\nmehrzeiliger String.\n"
|
||||
|
||||
# Alles Strings werden in UTF-8 enkodiert:
|
||||
"héllò" #=> "héllò"
|
||||
|
||||
# Eigentlich sind Strings in Wahrheit nur binaries und 'char lists' einfach
|
||||
# Listen.
|
||||
<<?a, ?b, ?c>> #=> "abc"
|
||||
[?a, ?b, ?c] #=> 'abc'
|
||||
|
||||
# In Elixir gibt `?a` den ASCII-Integer für den Buchstaben zurück.
|
||||
?a #=> 97
|
||||
|
||||
# Um Listen zu verbinden gibt es den Operator '++', für binaries nutzt man '<>'
|
||||
[1,2,3] ++ [4,5] #=> [1,2,3,4,5]
|
||||
'hello ' ++ 'world' #=> 'hello world'
|
||||
|
||||
<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
|
||||
"hello " <> "world" #=> "hello world"
|
||||
|
||||
## ---------------------------
|
||||
## -- Operatoren
|
||||
## ---------------------------
|
||||
|
||||
# Einfache Arithmetik
|
||||
1 + 1 #=> 2
|
||||
10 - 5 #=> 5
|
||||
5 * 2 #=> 10
|
||||
10 / 2 #=> 5.0
|
||||
|
||||
# In Elixir gibt der Operator '/' immer einen Float-Wert zurück.
|
||||
|
||||
# Für Division mit ganzzahligen Ergebnis gibt es 'div'
|
||||
div(10, 2) #=> 5
|
||||
|
||||
# Um den Rest der ganzzahligen Division zu erhalten gibt es 'rem'
|
||||
rem(10, 3) #=> 1
|
||||
|
||||
# Natürlich gibt es auch Operatoren für Booleans: 'or', 'and' und 'not'. Diese
|
||||
# Operatoren erwarten einen Boolean als erstes Argument.
|
||||
true and true #=> true
|
||||
false or true #=> true
|
||||
# 1 and true #=> ** (ArgumentError) argument error
|
||||
|
||||
# Elixir bietet auch '||', '&&' und '!', die Argumente jedweden Typs
|
||||
# akzeptieren. Alle Werte außer 'false' und 'nil' werden zu wahr evaluiert.
|
||||
1 || true #=> 1
|
||||
false && 1 #=> false
|
||||
nil && 20 #=> nil
|
||||
|
||||
!true #=> false
|
||||
|
||||
# Für Vergleiche gibt es die Operatoren `==`, `!=`, `===`, `!==`, `<=`, `>=`,
|
||||
# `<` und `>`
|
||||
1 == 1 #=> true
|
||||
1 != 1 #=> false
|
||||
1 < 2 #=> true
|
||||
|
||||
# '===' und '!==' sind strikter beim Vergleich von Integern und Floats:
|
||||
1 == 1.0 #=> true
|
||||
1 === 1.0 #=> false
|
||||
|
||||
# Es ist außerdem möglich zwei verschiedene Datentypen zu vergleichen:
|
||||
1 < :hello #=> true
|
||||
|
||||
# Die gesamte Ordnung über die Datentypen ist wie folgt definiert:
|
||||
# number < atom < reference < functions < port < pid < tuple < list < bitstring
|
||||
|
||||
# Um Joe Armstrong zu zitieren: "The actual order is not important, but that a
|
||||
# total ordering is well defined is important."
|
||||
|
||||
## ---------------------------
|
||||
## -- Kontrollstrukturen
|
||||
## ---------------------------
|
||||
|
||||
# Es gibt die `if`-Verzweigung
|
||||
if false do
|
||||
"Dies wird nie jemand sehen..."
|
||||
else
|
||||
"...aber dies!"
|
||||
end
|
||||
|
||||
# ...und ebenso `unless`
|
||||
unless true do
|
||||
"Dies wird nie jemand sehen..."
|
||||
else
|
||||
"...aber dies!"
|
||||
end
|
||||
|
||||
# Du erinnerst dich an 'pattern matching'? Viele Kontrollstrukturen in Elixir
|
||||
# arbeiten damit.
|
||||
|
||||
# 'case' erlaubt es uns Werte mit vielerlei Mustern zu vergleichen.
|
||||
case {:one, :two} do
|
||||
{:four, :five} ->
|
||||
"Das wird nicht passen"
|
||||
{:one, x} ->
|
||||
"Das schon und außerdem wird es ':two' dem Wert 'x' zuweisen."
|
||||
_ ->
|
||||
"Dieser Fall greift immer."
|
||||
end
|
||||
|
||||
# Es ist eine übliche Praxis '_' einen Wert zuzuweisen, sofern dieser Wert
|
||||
# nicht weiter verwendet wird.
|
||||
# Wenn wir uns zum Beispiel nur für den Kopf einer Liste interessieren:
|
||||
[kopf | _] = [1,2,3]
|
||||
kopf #=> 1
|
||||
|
||||
# Für bessere Lesbarkeit können wir auch das Folgende machen:
|
||||
[kopf | _rest] = [:a, :b, :c]
|
||||
kopf #=> :a
|
||||
|
||||
# Mit 'cond' können diverse Bedingungen zur selben Zeit überprüft werden. Man
|
||||
# benutzt 'cond' statt viele if-Verzweigungen zu verschachteln.
|
||||
cond do
|
||||
1 + 1 == 3 ->
|
||||
"Ich werde nie aufgerufen."
|
||||
2 * 5 == 12 ->
|
||||
"Ich auch nicht."
|
||||
1 + 2 == 3 ->
|
||||
"Aber ich!"
|
||||
end
|
||||
|
||||
# Es ist üblich eine letzte Bedingung einzufügen, die immer zu wahr evaluiert.
|
||||
cond do
|
||||
1 + 1 == 3 ->
|
||||
"Ich werde nie aufgerufen."
|
||||
2 * 5 == 12 ->
|
||||
"Ich auch nicht."
|
||||
true ->
|
||||
"Aber ich! (dies ist im Grunde ein 'else')"
|
||||
end
|
||||
|
||||
# 'try/catch' wird verwendet um Werte zu fangen, die zuvor 'geworfen' wurden.
|
||||
# Das Konstrukt unterstützt außerdem eine 'after'-Klausel die aufgerufen wird,
|
||||
# egal ob zuvor ein Wert gefangen wurde.
|
||||
try do
|
||||
throw(:hello)
|
||||
catch
|
||||
nachricht -> "#{nachricht} gefangen."
|
||||
after
|
||||
IO.puts("Ich bin die 'after'-Klausel.")
|
||||
end
|
||||
#=> Ich bin die 'after'-Klausel.
|
||||
# ":hello gefangen"
|
||||
|
||||
## ---------------------------
|
||||
## -- Module und Funktionen
|
||||
## ---------------------------
|
||||
|
||||
# Anonyme Funktionen (man beachte den Punkt)
|
||||
square = fn(x) -> x * x end
|
||||
square.(5) #=> 25
|
||||
|
||||
# Anonyme Funktionen unterstützen auch 'pattern' und 'guards'. Guards erlauben
|
||||
# es die Mustererkennung zu justieren und werden mit dem Schlüsselwort 'when'
|
||||
# eingeführt:
|
||||
f = fn
|
||||
x, y when x > 0 -> x + y
|
||||
x, y -> x * y
|
||||
end
|
||||
|
||||
f.(1, 3) #=> 4
|
||||
f.(-1, 3) #=> -3
|
||||
|
||||
# Elixir bietet zahlreiche eingebaute Funktionen. Diese sind im gleichen
|
||||
# Geltungsbereich ('scope') verfügbar.
|
||||
is_number(10) #=> true
|
||||
is_list("hello") #=> false
|
||||
elem({1,2,3}, 0) #=> 1
|
||||
|
||||
# Mehrere Funktionen können in einem Modul gruppiert werden. Innerhalb eines
|
||||
# Moduls ist es möglich mit dem Schlüsselwort 'def' eine Funktion zu
|
||||
# definieren.
|
||||
defmodule Math do
|
||||
def sum(a, b) do
|
||||
a + b
|
||||
end
|
||||
|
||||
def square(x) do
|
||||
x * x
|
||||
end
|
||||
end
|
||||
|
||||
Math.sum(1, 2) #=> 3
|
||||
Math.square(3) #=> 9
|
||||
|
||||
# Um unser einfaches Mathe-Modul zu kompilieren muss es unter 'math.ex'
|
||||
# gesichert werden. Anschließend kann es mit 'elixirc' im Terminal aufgerufen
|
||||
# werden: elixirc math.ex
|
||||
|
||||
# Innerhalb eines Moduls definieren wir private Funktionen mit 'defp'. Eine
|
||||
# Funktion, die mit 'def' erstellt wurde, kann von anderen Modulen aufgerufen
|
||||
# werden; eine private Funktion kann nur lokal angesprochen werden.
|
||||
defmodule PrivateMath do
|
||||
def sum(a, b) do
|
||||
do_sum(a, b)
|
||||
end
|
||||
|
||||
defp do_sum(a, b) do
|
||||
a + b
|
||||
end
|
||||
end
|
||||
|
||||
PrivateMath.sum(1, 2) #=> 3
|
||||
# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
|
||||
|
||||
# Auch Funktionsdeklarationen unterstützen 'guards' und Mustererkennung:
|
||||
defmodule Geometry do
|
||||
def area({:rectangle, w, h}) do
|
||||
w * h
|
||||
end
|
||||
|
||||
def area({:circle, r}) when is_number(r) do
|
||||
3.14 * r * r
|
||||
end
|
||||
end
|
||||
|
||||
Geometry.area({:rectangle, 2, 3}) #=> 6
|
||||
Geometry.area({:circle, 3}) #=> 28.25999999999999801048
|
||||
# Geometry.area({:circle, "not_a_number"})
|
||||
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
|
||||
|
||||
# Wegen der Unveränderlichkeit von Variablen ist Rekursion ein wichtiger
|
||||
# Bestandteil von Elixir.
|
||||
defmodule Recursion do
|
||||
def sum_list([head | tail], acc) do
|
||||
sum_list(tail, acc + head)
|
||||
end
|
||||
|
||||
def sum_list([], acc) do
|
||||
acc
|
||||
end
|
||||
end
|
||||
|
||||
Recursion.sum_list([1,2,3], 0) #=> 6
|
||||
|
||||
# Elixir-Module unterstützen Attribute. Es gibt eingebaute Attribute, ebenso
|
||||
# ist es möglich eigene Attribute hinzuzufügen.
|
||||
defmodule MyMod do
|
||||
@moduledoc """
|
||||
Dies ist ein eingebautes Attribut in einem Beispiel-Modul
|
||||
"""
|
||||
|
||||
@my_data 100 # Dies ist ein selbst-definiertes Attribut.
|
||||
IO.inspect(@my_data) #=> 100
|
||||
end
|
||||
|
||||
## ---------------------------
|
||||
## -- 'Records' und Ausnahmebehandlung
|
||||
## ---------------------------
|
||||
|
||||
# 'Records' sind im Grunde Strukturen, die es erlauben einem Wert einen eigenen
|
||||
# Namen zuzuweisen.
|
||||
defrecord Person, name: nil, age: 0, height: 0
|
||||
|
||||
joe_info = Person.new(name: "Joe", age: 30, height: 180)
|
||||
#=> Person[name: "Joe", age: 30, height: 180]
|
||||
|
||||
# Zugriff auf den Wert von 'name'
|
||||
joe_info.name #=> "Joe"
|
||||
|
||||
# Den Wert von 'age' überschreiben
|
||||
joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180]
|
||||
|
||||
# Der 'try'-Block wird zusammen mit dem 'rescue'-Schlüsselwort dazu verwendet,
|
||||
# um Ausnahmen beziehungsweise Fehler zu behandeln.
|
||||
try do
|
||||
raise "Irgendein Fehler."
|
||||
rescue
|
||||
RuntimeError -> "Laufzeit-Fehler gefangen."
|
||||
_error -> "Und dies fängt jeden Fehler."
|
||||
end
|
||||
|
||||
# Alle Ausnahmen haben das Attribut 'message'
|
||||
try do
|
||||
raise "ein Fehler"
|
||||
rescue
|
||||
x in [RuntimeError] ->
|
||||
x.message
|
||||
end
|
||||
|
||||
## ---------------------------
|
||||
## -- Nebenläufigkeit
|
||||
## ---------------------------
|
||||
|
||||
# Elixir beruht auf dem Aktoren-Model zur Behandlung der Nebenläufigkeit. Alles
|
||||
# was man braucht um in Elixir nebenläufige Programme zu schreiben sind drei
|
||||
# Primitive: Prozesse erzeugen, Nachrichten senden und Nachrichten empfangen.
|
||||
|
||||
# Um einen neuen Prozess zu erzeugen nutzen wir die 'spawn'-Funktion, die
|
||||
# wiederum eine Funktion als Argument entgegen nimmt.
|
||||
f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
|
||||
spawn(f) #=> #PID<0.40.0>
|
||||
|
||||
# 'spawn' gibt eine pid (einen Identifikator des Prozesses) zurück. Diese kann
|
||||
# nun verwendet werden, um Nachrichten an den Prozess zu senden. Um
|
||||
# zu senden nutzen wir den '<-' Operator. Damit das alles Sinn macht müssen wir
|
||||
# in der Lage sein Nachrichten zu empfangen. Dies wird mit dem
|
||||
# 'receive'-Mechanismus sichergestellt:
|
||||
defmodule Geometry do
|
||||
def area_loop do
|
||||
receive do
|
||||
{:rectangle, w, h} ->
|
||||
IO.puts("Area = #{w * h}")
|
||||
area_loop()
|
||||
{:circle, r} ->
|
||||
IO.puts("Area = #{3.14 * r * r}")
|
||||
area_loop()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Kompiliere das Modul, starte einen Prozess und gib die 'area_loop' Funktion
|
||||
# in der Shell mit, etwa so:
|
||||
pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0>
|
||||
|
||||
# Sende eine Nachricht an die 'pid', die ein Muster im 'receive'-Ausdruck
|
||||
# erfüllt:
|
||||
pid <- {:rectangle, 2, 3}
|
||||
#=> Area = 6
|
||||
# {:rectangle,2,3}
|
||||
|
||||
pid <- {:circle, 2}
|
||||
#=> Area = 12.56000000000000049738
|
||||
# {:circle,2}
|
||||
|
||||
# Die Shell selbst ist ein Prozess und mit dem Schlüsselwort 'self' kann man
|
||||
# die aktuelle pid herausfinden.
|
||||
self() #=> #PID<0.27.0>
|
||||
|
||||
```
|
||||
|
||||
## Referenzen und weitere Lektüre
|
||||
|
||||
* [Getting started guide](http://elixir-lang.org/getting_started/1.html) auf der [elixir Website](http://elixir-lang.org)
|
||||
* [Elixir Documentation](http://elixir-lang.org/docs/master/)
|
||||
* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) von Fred Hebert
|
||||
* "Programming Erlang: Software for a Concurrent World" von Joe Armstrong
|
||||
---
|
||||
language: Elixir
|
||||
contributors:
|
||||
- ["Joao Marques", "http://github.com/mrshankly"]
|
||||
translators:
|
||||
- ["Gregor Große-Bölting", "http://www.ideen-und-soehne.de"]
|
||||
filename: learnelixir-de.ex
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Elixir ist eine moderne, funktionale Sprache für die Erlang VM. Sie ist voll
|
||||
kompatibel mit Erlang, verfügt aber über eine freundlichere Syntax und bringt
|
||||
viele Features mit.
|
||||
|
||||
```ruby
|
||||
# Einzeilige Kommentare werden mit der Raute gesetzt.
|
||||
|
||||
# Es gibt keine mehrzeiligen Kommentare;
|
||||
# es ist aber problemlos möglich mehrere einzeilige Kommentare hintereinander
|
||||
# zu setzen (so wie hier).
|
||||
|
||||
# Mit 'iex' ruft man die Elixir-Shell auf.
|
||||
# Zum kompilieren von Modulen dient der Befehl 'elixirc'.
|
||||
|
||||
# Beide Befehle sollten als Umgebungsvariable gesetzt sein, wenn Elixir korrekt
|
||||
# installiert wurde.
|
||||
|
||||
## ---------------------------
|
||||
## -- Basistypen
|
||||
## ---------------------------
|
||||
|
||||
# Es gibt Nummern:
|
||||
3 # Integer
|
||||
0x1F # Integer
|
||||
3.0 # Float
|
||||
|
||||
# Für bessere Lesbarkeit des Codes können Unterstriche "_" als Trennzeichen verwendet werden
|
||||
1_000_000 == 1000000 # Integer
|
||||
1_000.567 == 1000.567 # Float
|
||||
|
||||
# Atome, das sind Literale, sind Konstanten mit Namen. Sie starten mit einem
|
||||
# ':'.
|
||||
:hello # Atom
|
||||
|
||||
# Außerdem gibt es Tupel, deren Werte im Arbeitsspeicher vorgehalten werden.
|
||||
{1,2,3} # Tupel
|
||||
|
||||
# Die Werte innerhalb eines Tupels können mit der 'elem'-Funktion ausgelesen
|
||||
# werden:
|
||||
elem({1, 2, 3}, 0) # => 1
|
||||
|
||||
# Listen sind als verkettete Listen implementiert.
|
||||
[1, 2, 3] # list
|
||||
|
||||
# Auf Kopf und Rest einer Liste kann wie folgt zugegriffen werden:
|
||||
[ kopf | rest ] = [1,2,3]
|
||||
kopf # => 1
|
||||
rest # => [2, 3]
|
||||
|
||||
# In Elixir, wie auch in Erlang, kennzeichnet '=' ein 'pattern matching'
|
||||
# (Musterabgleich) und keine Zuweisung.
|
||||
# Das heißt, dass die linke Seite auf die rechte Seite 'abgeglichen' wird.
|
||||
# Auf diese Weise kann im Beispiel oben auf Kopf und Rest der Liste zugegriffen
|
||||
# werden.
|
||||
|
||||
# Ein Musterabgleich wird einen Fehler werfen, wenn die beiden Seiten nicht
|
||||
# zusammenpassen.
|
||||
# Im folgenden Beispiel haben die Tupel eine unterschiedliche Anzahl an
|
||||
# Elementen:
|
||||
{a, b, c} = {1, 2} #=> ** (MatchError) no match of right hand side value: {1,2}
|
||||
|
||||
# Es gibt außerdem 'binaries',
|
||||
<<1,2,3>> # binary.
|
||||
|
||||
# Strings und 'char lists'
|
||||
"hello" # String
|
||||
'hello' # Char-Liste
|
||||
|
||||
# ... und mehrzeilige Strings
|
||||
"""
|
||||
Ich bin ein
|
||||
mehrzeiliger String.
|
||||
"""
|
||||
#=> "Ich bin ein\nmehrzeiliger String.\n"
|
||||
|
||||
# Alles Strings werden in UTF-8 enkodiert:
|
||||
"héllò" #=> "héllò"
|
||||
|
||||
# Eigentlich sind Strings in Wahrheit nur binaries und 'char lists' einfach
|
||||
# Listen.
|
||||
<<?a, ?b, ?c>> #=> "abc"
|
||||
[?a, ?b, ?c] #=> 'abc'
|
||||
|
||||
# In Elixir gibt `?a` den ASCII-Integer für den Buchstaben zurück.
|
||||
?a #=> 97
|
||||
|
||||
# Um Listen zu verbinden gibt es den Operator '++', für binaries nutzt man '<>'
|
||||
[1,2,3] ++ [4,5] #=> [1,2,3,4,5]
|
||||
'hello ' ++ 'world' #=> 'hello world'
|
||||
|
||||
<<1,2,3>> <> <<4,5>> #=> <<1,2,3,4,5>>
|
||||
"hello " <> "world" #=> "hello world"
|
||||
|
||||
## ---------------------------
|
||||
## -- Operatoren
|
||||
## ---------------------------
|
||||
|
||||
# Einfache Arithmetik
|
||||
1 + 1 #=> 2
|
||||
10 - 5 #=> 5
|
||||
5 * 2 #=> 10
|
||||
10 / 2 #=> 5.0
|
||||
|
||||
# In Elixir gibt der Operator '/' immer einen Float-Wert zurück.
|
||||
|
||||
# Für Division mit ganzzahligen Ergebnis gibt es 'div'
|
||||
div(10, 2) #=> 5
|
||||
|
||||
# Um den Rest der ganzzahligen Division zu erhalten gibt es 'rem'
|
||||
rem(10, 3) #=> 1
|
||||
|
||||
# Natürlich gibt es auch Operatoren für Booleans: 'or', 'and' und 'not'. Diese
|
||||
# Operatoren erwarten einen Boolean als erstes Argument.
|
||||
true and true #=> true
|
||||
false or true #=> true
|
||||
# 1 and true #=> ** (ArgumentError) argument error
|
||||
|
||||
# Elixir bietet auch '||', '&&' und '!', die Argumente jedweden Typs
|
||||
# akzeptieren. Alle Werte außer 'false' und 'nil' werden zu wahr evaluiert.
|
||||
1 || true #=> 1
|
||||
false && 1 #=> false
|
||||
nil && 20 #=> nil
|
||||
|
||||
!true #=> false
|
||||
|
||||
# Für Vergleiche gibt es die Operatoren `==`, `!=`, `===`, `!==`, `<=`, `>=`,
|
||||
# `<` und `>`
|
||||
1 == 1 #=> true
|
||||
1 != 1 #=> false
|
||||
1 < 2 #=> true
|
||||
|
||||
# '===' und '!==' sind strikter beim Vergleich von Integern und Floats:
|
||||
1 == 1.0 #=> true
|
||||
1 === 1.0 #=> false
|
||||
|
||||
# Es ist außerdem möglich zwei verschiedene Datentypen zu vergleichen:
|
||||
1 < :hello #=> true
|
||||
|
||||
# Die gesamte Ordnung über die Datentypen ist wie folgt definiert:
|
||||
# number < atom < reference < functions < port < pid < tuple < list < bitstring
|
||||
|
||||
# Um Joe Armstrong zu zitieren: "The actual order is not important, but that a
|
||||
# total ordering is well defined is important."
|
||||
|
||||
## ---------------------------
|
||||
## -- Kontrollstrukturen
|
||||
## ---------------------------
|
||||
|
||||
# Es gibt die `if`-Verzweigung
|
||||
if false do
|
||||
"Dies wird nie jemand sehen..."
|
||||
else
|
||||
"...aber dies!"
|
||||
end
|
||||
|
||||
# ...und ebenso `unless`
|
||||
unless true do
|
||||
"Dies wird nie jemand sehen..."
|
||||
else
|
||||
"...aber dies!"
|
||||
end
|
||||
|
||||
# Du erinnerst dich an 'pattern matching'? Viele Kontrollstrukturen in Elixir
|
||||
# arbeiten damit.
|
||||
|
||||
# 'case' erlaubt es uns Werte mit vielerlei Mustern zu vergleichen.
|
||||
case {:one, :two} do
|
||||
{:four, :five} ->
|
||||
"Das wird nicht passen"
|
||||
{:one, x} ->
|
||||
"Das schon und außerdem wird es ':two' dem Wert 'x' zuweisen."
|
||||
_ ->
|
||||
"Dieser Fall greift immer."
|
||||
end
|
||||
|
||||
# Es ist eine übliche Praxis '_' einen Wert zuzuweisen, sofern dieser Wert
|
||||
# nicht weiter verwendet wird.
|
||||
# Wenn wir uns zum Beispiel nur für den Kopf einer Liste interessieren:
|
||||
[kopf | _] = [1,2,3]
|
||||
kopf #=> 1
|
||||
|
||||
# Für bessere Lesbarkeit können wir auch das Folgende machen:
|
||||
[kopf | _rest] = [:a, :b, :c]
|
||||
kopf #=> :a
|
||||
|
||||
# Mit 'cond' können diverse Bedingungen zur selben Zeit überprüft werden. Man
|
||||
# benutzt 'cond' statt viele if-Verzweigungen zu verschachteln.
|
||||
cond do
|
||||
1 + 1 == 3 ->
|
||||
"Ich werde nie aufgerufen."
|
||||
2 * 5 == 12 ->
|
||||
"Ich auch nicht."
|
||||
1 + 2 == 3 ->
|
||||
"Aber ich!"
|
||||
end
|
||||
|
||||
# Es ist üblich eine letzte Bedingung einzufügen, die immer zu wahr evaluiert.
|
||||
cond do
|
||||
1 + 1 == 3 ->
|
||||
"Ich werde nie aufgerufen."
|
||||
2 * 5 == 12 ->
|
||||
"Ich auch nicht."
|
||||
true ->
|
||||
"Aber ich! (dies ist im Grunde ein 'else')"
|
||||
end
|
||||
|
||||
# 'try/catch' wird verwendet um Werte zu fangen, die zuvor 'geworfen' wurden.
|
||||
# Das Konstrukt unterstützt außerdem eine 'after'-Klausel die aufgerufen wird,
|
||||
# egal ob zuvor ein Wert gefangen wurde.
|
||||
try do
|
||||
throw(:hello)
|
||||
catch
|
||||
nachricht -> "#{nachricht} gefangen."
|
||||
after
|
||||
IO.puts("Ich bin die 'after'-Klausel.")
|
||||
end
|
||||
#=> Ich bin die 'after'-Klausel.
|
||||
# ":hello gefangen"
|
||||
|
||||
## ---------------------------
|
||||
## -- Module und Funktionen
|
||||
## ---------------------------
|
||||
|
||||
# Anonyme Funktionen (man beachte den Punkt)
|
||||
square = fn(x) -> x * x end
|
||||
square.(5) #=> 25
|
||||
|
||||
# Anonyme Funktionen unterstützen auch 'pattern' und 'guards'. Guards erlauben
|
||||
# es die Mustererkennung zu justieren und werden mit dem Schlüsselwort 'when'
|
||||
# eingeführt:
|
||||
f = fn
|
||||
x, y when x > 0 -> x + y
|
||||
x, y -> x * y
|
||||
end
|
||||
|
||||
f.(1, 3) #=> 4
|
||||
f.(-1, 3) #=> -3
|
||||
|
||||
# Elixir bietet zahlreiche eingebaute Funktionen. Diese sind im gleichen
|
||||
# Geltungsbereich ('scope') verfügbar.
|
||||
is_number(10) #=> true
|
||||
is_list("hello") #=> false
|
||||
elem({1,2,3}, 0) #=> 1
|
||||
|
||||
# Mehrere Funktionen können in einem Modul gruppiert werden. Innerhalb eines
|
||||
# Moduls ist es möglich mit dem Schlüsselwort 'def' eine Funktion zu
|
||||
# definieren.
|
||||
defmodule Math do
|
||||
def sum(a, b) do
|
||||
a + b
|
||||
end
|
||||
|
||||
def square(x) do
|
||||
x * x
|
||||
end
|
||||
end
|
||||
|
||||
Math.sum(1, 2) #=> 3
|
||||
Math.square(3) #=> 9
|
||||
|
||||
# Um unser einfaches Mathe-Modul zu kompilieren muss es unter 'math.ex'
|
||||
# gesichert werden. Anschließend kann es mit 'elixirc' im Terminal aufgerufen
|
||||
# werden: elixirc math.ex
|
||||
|
||||
# Innerhalb eines Moduls definieren wir private Funktionen mit 'defp'. Eine
|
||||
# Funktion, die mit 'def' erstellt wurde, kann von anderen Modulen aufgerufen
|
||||
# werden; eine private Funktion kann nur lokal angesprochen werden.
|
||||
defmodule PrivateMath do
|
||||
def sum(a, b) do
|
||||
do_sum(a, b)
|
||||
end
|
||||
|
||||
defp do_sum(a, b) do
|
||||
a + b
|
||||
end
|
||||
end
|
||||
|
||||
PrivateMath.sum(1, 2) #=> 3
|
||||
# PrivateMath.do_sum(1, 2) #=> ** (UndefinedFunctionError)
|
||||
|
||||
# Auch Funktionsdeklarationen unterstützen 'guards' und Mustererkennung:
|
||||
defmodule Geometry do
|
||||
def area({:rectangle, w, h}) do
|
||||
w * h
|
||||
end
|
||||
|
||||
def area({:circle, r}) when is_number(r) do
|
||||
3.14 * r * r
|
||||
end
|
||||
end
|
||||
|
||||
Geometry.area({:rectangle, 2, 3}) #=> 6
|
||||
Geometry.area({:circle, 3}) #=> 28.25999999999999801048
|
||||
# Geometry.area({:circle, "not_a_number"})
|
||||
#=> ** (FunctionClauseError) no function clause matching in Geometry.area/1
|
||||
|
||||
# Wegen der Unveränderlichkeit von Variablen ist Rekursion ein wichtiger
|
||||
# Bestandteil von Elixir.
|
||||
defmodule Recursion do
|
||||
def sum_list([head | tail], acc) do
|
||||
sum_list(tail, acc + head)
|
||||
end
|
||||
|
||||
def sum_list([], acc) do
|
||||
acc
|
||||
end
|
||||
end
|
||||
|
||||
Recursion.sum_list([1,2,3], 0) #=> 6
|
||||
|
||||
# Elixir-Module unterstützen Attribute. Es gibt eingebaute Attribute, ebenso
|
||||
# ist es möglich eigene Attribute hinzuzufügen.
|
||||
defmodule MyMod do
|
||||
@moduledoc """
|
||||
Dies ist ein eingebautes Attribut in einem Beispiel-Modul
|
||||
"""
|
||||
|
||||
@my_data 100 # Dies ist ein selbst-definiertes Attribut.
|
||||
IO.inspect(@my_data) #=> 100
|
||||
end
|
||||
|
||||
## ---------------------------
|
||||
## -- 'Records' und Ausnahmebehandlung
|
||||
## ---------------------------
|
||||
|
||||
# 'Records' sind im Grunde Strukturen, die es erlauben einem Wert einen eigenen
|
||||
# Namen zuzuweisen.
|
||||
defrecord Person, name: nil, age: 0, height: 0
|
||||
|
||||
joe_info = Person.new(name: "Joe", age: 30, height: 180)
|
||||
#=> Person[name: "Joe", age: 30, height: 180]
|
||||
|
||||
# Zugriff auf den Wert von 'name'
|
||||
joe_info.name #=> "Joe"
|
||||
|
||||
# Den Wert von 'age' überschreiben
|
||||
joe_info = joe_info.age(31) #=> Person[name: "Joe", age: 31, height: 180]
|
||||
|
||||
# Der 'try'-Block wird zusammen mit dem 'rescue'-Schlüsselwort dazu verwendet,
|
||||
# um Ausnahmen beziehungsweise Fehler zu behandeln.
|
||||
try do
|
||||
raise "Irgendein Fehler."
|
||||
rescue
|
||||
RuntimeError -> "Laufzeit-Fehler gefangen."
|
||||
_error -> "Und dies fängt jeden Fehler."
|
||||
end
|
||||
|
||||
# Alle Ausnahmen haben das Attribut 'message'
|
||||
try do
|
||||
raise "ein Fehler"
|
||||
rescue
|
||||
x in [RuntimeError] ->
|
||||
x.message
|
||||
end
|
||||
|
||||
## ---------------------------
|
||||
## -- Nebenläufigkeit
|
||||
## ---------------------------
|
||||
|
||||
# Elixir beruht auf dem Aktoren-Model zur Behandlung der Nebenläufigkeit. Alles
|
||||
# was man braucht um in Elixir nebenläufige Programme zu schreiben sind drei
|
||||
# Primitive: Prozesse erzeugen, Nachrichten senden und Nachrichten empfangen.
|
||||
|
||||
# Um einen neuen Prozess zu erzeugen nutzen wir die 'spawn'-Funktion, die
|
||||
# wiederum eine Funktion als Argument entgegen nimmt.
|
||||
f = fn -> 2 * 2 end #=> #Function<erl_eval.20.80484245>
|
||||
spawn(f) #=> #PID<0.40.0>
|
||||
|
||||
# 'spawn' gibt eine pid (einen Identifikator des Prozesses) zurück. Diese kann
|
||||
# nun verwendet werden, um Nachrichten an den Prozess zu senden. Um
|
||||
# zu senden nutzen wir den '<-' Operator. Damit das alles Sinn macht müssen wir
|
||||
# in der Lage sein Nachrichten zu empfangen. Dies wird mit dem
|
||||
# 'receive'-Mechanismus sichergestellt:
|
||||
defmodule Geometry do
|
||||
def area_loop do
|
||||
receive do
|
||||
{:rectangle, w, h} ->
|
||||
IO.puts("Area = #{w * h}")
|
||||
area_loop()
|
||||
{:circle, r} ->
|
||||
IO.puts("Area = #{3.14 * r * r}")
|
||||
area_loop()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Kompiliere das Modul, starte einen Prozess und gib die 'area_loop' Funktion
|
||||
# in der Shell mit, etwa so:
|
||||
pid = spawn(fn -> Geometry.area_loop() end) #=> #PID<0.40.0>
|
||||
|
||||
# Sende eine Nachricht an die 'pid', die ein Muster im 'receive'-Ausdruck
|
||||
# erfüllt:
|
||||
pid <- {:rectangle, 2, 3}
|
||||
#=> Area = 6
|
||||
# {:rectangle,2,3}
|
||||
|
||||
pid <- {:circle, 2}
|
||||
#=> Area = 12.56000000000000049738
|
||||
# {:circle,2}
|
||||
|
||||
# Die Shell selbst ist ein Prozess und mit dem Schlüsselwort 'self' kann man
|
||||
# die aktuelle pid herausfinden.
|
||||
self() #=> #PID<0.27.0>
|
||||
```
|
||||
|
||||
## Referenzen und weitere Lektüre
|
||||
|
||||
* [Getting started guide](http://elixir-lang.org/getting_started/1.html) auf der [elixir Website](http://elixir-lang.org)
|
||||
* [Elixir Documentation](http://elixir-lang.org/docs/master/)
|
||||
* ["Learn You Some Erlang for Great Good!"](http://learnyousomeerlang.com/) von Fred Hebert
|
||||
* "Programming Erlang: Software for a Concurrent World" von Joe Armstrong
|
||||
|
@ -33,7 +33,7 @@ Hauptmerkmal von Elm sind die ausführlichen und gut erklärten Fehlermeldungen.
|
||||
-- Exponenten
|
||||
5 ^ 2 -- 25
|
||||
|
||||
-- Boolsche Werte
|
||||
-- Boolesche Werte
|
||||
not True -- False
|
||||
not False -- True
|
||||
1 == 1 -- True
|
||||
@ -189,7 +189,7 @@ listLength aList =
|
||||
-- Klammern bietet die Möglichkeit der Bevorrangung.
|
||||
cos (degrees 30) ^ 2 + sin (degrees 30) ^ 2 -- 1
|
||||
-- Als erstes wird die Funktion "degrees" mit dem Wert 30 aufgerufen.
|
||||
-- Danach wird das Ergenis davon den Funktionen "cos", bzw. "sin" übergeben.
|
||||
-- Danach wird das Ergebnis davon den Funktionen "cos", bzw. "sin" übergeben.
|
||||
-- Dann wird das Ergebnis davon mit 2 quadriert und als letztes werden diese
|
||||
-- beiden Werte dann addiert.
|
||||
|
||||
@ -238,7 +238,7 @@ append [1,1,2] [3,5,8] -- [1,1,2,3,5,8]
|
||||
|
||||
{-- Eigene Datentypen erstellen --}
|
||||
|
||||
-- Ein "Record" ist ähnlich wie ein Tupel, nur das jedes Feld einen Namne hat.
|
||||
-- Ein "Record" ist ähnlich wie ein Tupel, nur das jedes Feld einen Namen hat.
|
||||
-- Dabei spielt die Reihenfolge keine Rolle.
|
||||
{ x = 3, y = 7 }
|
||||
|
||||
@ -253,7 +253,7 @@ append [1,1,2] [3,5,8] -- [1,1,2,3,5,8]
|
||||
{ person |
|
||||
name = "George" }
|
||||
|
||||
-- Mehrere Felder aufeinmal ändern unter Verwendung des alten Wertes.
|
||||
-- Mehrere Felder auf einmal ändern unter Verwendung des alten Wertes.
|
||||
{ particle |
|
||||
position = particle.position + particle.velocity,
|
||||
velocity = particle.velocity + particle.acceleration }
|
||||
@ -274,7 +274,7 @@ otherOrigin : Point3D
|
||||
otherOrigin =
|
||||
Point3D 0 0 0
|
||||
|
||||
-- Aber es ist immernoch der selbe Typ, da es nur ein Alias ist!
|
||||
-- Aber es ist immer noch derselbe Typ, da es nur ein Alias ist!
|
||||
origin == otherOrigin -- True
|
||||
|
||||
-- Neben den Records gibt es auch noch so genannte Summentypen.
|
||||
@ -309,7 +309,7 @@ leftmostElement tree =
|
||||
-- Die Kernbibliotheken und andere Bibliotheken sind in Module aufgeteilt.
|
||||
-- Für große Projekte können auch eigene Module erstellt werden.
|
||||
|
||||
-- Eine Modul beginnt mit ganz oben. Ohne diese Angabe befindet man sich
|
||||
-- Eine Modul beginnt ganz oben. Ohne diese Angabe befindet man sich
|
||||
-- automatisch im Modul "Main".
|
||||
module Name where
|
||||
|
||||
@ -337,13 +337,13 @@ $ elm make MyFile.elm
|
||||
-- "elm-package.json"-Datei anlegen, die alle Informationen des Projektes
|
||||
-- speichert.
|
||||
|
||||
-- Der Reactor ist ein Server, welche alle Dateinen kompiliert und ausführt.
|
||||
-- Der Reactor ist ein Server, welcher alle Dateien kompiliert und ausführt.
|
||||
$ elm reactor
|
||||
|
||||
-- Starte das REPL (read-eval-print-loop).
|
||||
$ elm repl
|
||||
|
||||
-- Bibliotheken werden durch den Github-Nutzernamen und ein Repository identifiziert.
|
||||
-- Bibliotheken werden durch den GitHub-Nutzernamen und ein Repository identifiziert.
|
||||
-- Installieren einer neuen Bibliothek.
|
||||
$ elm package install elm-lang/html
|
||||
-- Diese wird der elm-package.json Datei hinzugefügt.
|
||||
@ -360,7 +360,7 @@ Noch ein paar weitere hilfreiche Ressourcen (in Englisch):
|
||||
|
||||
- Die [Elm Homepage](http://elm-lang.org/). Dort findest du:
|
||||
|
||||
- [Anleitung zur Installierung von Elm](http://elm-lang.org/install)
|
||||
- [Anleitung zur Installation von Elm](http://elm-lang.org/install)
|
||||
- [Dokumentation](http://elm-lang.org/docs), sowie eine [Referenz zur Syntax](http://elm-lang.org/docs/syntax)
|
||||
- Viele hilfreiche [Beispiele](http://elm-lang.org/examples)
|
||||
|
||||
|
@ -82,10 +82,10 @@ Zeilenumbrüche beinhalten.` // Selber Zeichenketten-Typ
|
||||
// nicht-ASCII Literal. Go Quelltext ist UTF-8 kompatibel.
|
||||
g := 'Σ' // Ein Runen-Typ, alias int32, gebraucht für unicode code points.
|
||||
|
||||
f := 3.14195 // float64, eine IEEE-754 64-bit Dezimalzahl
|
||||
f := 3.14159 // float64, eine IEEE-754 64-bit Dezimalzahl
|
||||
c := 3 + 4i // complex128, besteht intern aus zwei float64-er
|
||||
|
||||
// "var"-Syntax mit Initalwert
|
||||
// "var"-Syntax mit Initialwert
|
||||
var u uint = 7 // Vorzeichenlos, aber die Größe ist implementationsabhängig
|
||||
var pi float32 = 22. / 7
|
||||
|
||||
@ -124,13 +124,13 @@ Zeilenumbrüche beinhalten.` // Selber Zeichenketten-Typ
|
||||
// keine Zeiger-Rechnungen. Fehler können sich durch "nil" einschleichen, jedoch
|
||||
// nicht durch erhöhen eines Zeigers.
|
||||
func learnMemory() (p, q *int) {
|
||||
// Die bennanten Rückgabewerte p & q sind vom Typ *int
|
||||
// Die benannten Rückgabewerte p & q sind vom Typ *int
|
||||
p = new(int) // Eingebaute Funktion "new" weist neuen Speicherplatz zu
|
||||
// Der zugewiesene Speicher ist mit 0 initialisiert, p ist nicht länger nil
|
||||
s := make([]int, 20) // So weist man 20 ints nebeneinander (im Speicher) zu
|
||||
s[3] = 7 // Einer von ihnen wird ein Wert zugewiesen
|
||||
r := -2 // Deklaration einer weiteren lokalen Variable
|
||||
return &s[3], &r // & gibt die Addresse einer Variable
|
||||
return &s[3], &r // & gibt die Adresse einer Variable
|
||||
}
|
||||
|
||||
func expensiveComputation() int {
|
||||
@ -292,7 +292,7 @@ func learnConcurrency() {
|
||||
|
||||
// Eine einzige Funktion aus dem http-Paket kann einen Webserver starten.
|
||||
func learnWebProgramming() {
|
||||
// Der erste Parameter von "ListenAndServe" ist eine TCP Addresse, an die
|
||||
// Der erste Parameter von "ListenAndServe" ist eine TCP Adresse, an die
|
||||
// sich angeschlossen werden soll.
|
||||
// Der zweite Parameter ist ein Interface, speziell: ein http.Handler
|
||||
err := http.ListenAndServe(":8080", pair{})
|
||||
@ -308,13 +308,13 @@ func (p pair) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
```
|
||||
|
||||
## Weitere Resourcen
|
||||
Informationen zu Go findet man auf der [offiziellen Go Webseite](http://golang.org/).
|
||||
Informationen zu Go findet man auf der [offiziellen Go Webseite](https://go.dev/).
|
||||
Dort gibt es unter anderem ein Tutorial und interaktive Quelltext-Beispiele, vor
|
||||
allem aber Dokumentation zur Sprache und den Paketen.
|
||||
|
||||
Auch zu empfehlen ist die Spezifikation von Go, die nach heutigen Standards sehr
|
||||
kurz und gut verständlich formuliert ist. Auf der Leseliste von Go-Neulingen
|
||||
ist außerdem der Quelltext der [Go standard Bibliothek](http://golang.org/src/pkg/)
|
||||
ist außerdem der Quelltext der [Go standard Bibliothek](https://go.dev/src/)
|
||||
einzusehen. Dieser kann als Referenz für leicht zu verstehendes und im idiomatischen Stil
|
||||
verfasstes Go dienen. Erreichbar ist der Quelltext auch durch das Klicken der Funktionsnamen
|
||||
in der [offiziellen Dokumentation von Go](http://golang.org/pkg/).
|
||||
in der [offiziellen Dokumentation von Go](https://go.dev/pkg/).
|
||||
|
@ -305,7 +305,6 @@ class Samuel
|
||||
|
||||
$cat = new Samuel();
|
||||
$cat instanceof KittenInterface === true; // True
|
||||
|
||||
```
|
||||
|
||||
## Weitere Informationen
|
||||
@ -318,5 +317,5 @@ besuchen.
|
||||
Die offizielle Webseite [hhvm.com](http://hhvm.com/) bietet Infos zum Download
|
||||
und zur Installation der HHVM.
|
||||
|
||||
Hack's [nicht-untersützte PHP Syntax-Elemente](http://docs.hhvm.com/manual/en/hack.unsupported.php)
|
||||
Hack's [nicht-unterstützte PHP Syntax-Elemente](http://docs.hhvm.com/manual/en/hack.unsupported.php)
|
||||
werden im offiziellen Handbuch beschrieben.
|
||||
|
@ -93,7 +93,7 @@ $ haml input_file.haml output_file.html
|
||||
/ andere Attribute können über den Hash angegeben werden:
|
||||
%a{:href => '#', :class => 'bar', :title => 'Bar'}
|
||||
|
||||
/ Booleesche Attribute können mit 'true' gesetzt werden:
|
||||
/ Boolesche Attribute können mit 'true' gesetzt werden:
|
||||
%input{:selected => true}
|
||||
|
||||
/ data-Attribute können in einem eigenen Hash im :data key angegeben werden:
|
||||
@ -141,13 +141,12 @@ $ haml input_file.haml output_file.html
|
||||
/ -------------------------------------------
|
||||
|
||||
/
|
||||
Mit dem Doppelpinkt können Haml Filter benutzt werden.
|
||||
Mit dem Doppelpunkt können Haml Filter benutzt werden.
|
||||
Zum Beispiel gibt es den :javascript Filter, mit dem inline JS
|
||||
geschrieben werden kann:
|
||||
|
||||
:javascript
|
||||
console.log('Dies ist ein <script>');
|
||||
|
||||
```
|
||||
|
||||
## Weitere Resourcen
|
||||
|
@ -50,7 +50,7 @@ not False -- True
|
||||
1 /= 1 -- False
|
||||
1 < 10 -- True
|
||||
|
||||
-- `not` ist eine Funktion die ein Argument entgegenimmt.
|
||||
-- `not` ist eine Funktion die ein Argument entgegennimmt.
|
||||
-- Haskell benötigt keine Klammern um Argumente.
|
||||
-- Sie werden einfach aufgelistet: func arg1 arg2 arg3...
|
||||
-- Wie man Funktionen definiert kommt weiter unten.
|
||||
@ -66,6 +66,8 @@ not False -- True
|
||||
|
||||
-- Ein String ist eine Liste von Zeichen.
|
||||
['H', 'a', 'l', 'l', 'o', '!'] -- "Hallo!"
|
||||
|
||||
-- Der "!!"-Operator extrahiert das Element an einem bestimmten Index
|
||||
"Das ist eine String" !! 0 -- 'D'
|
||||
|
||||
|
||||
@ -87,7 +89,7 @@ not False -- True
|
||||
[5..1] -- [], da Haskell standardmässig inkrementiert.
|
||||
[5,4..1] -- [5,4,3,2,1]
|
||||
|
||||
-- Der "!!"-Operator extrahiert das Element an einem bestimmten Index:
|
||||
-- Ein Element per Index extrahieren:
|
||||
[1..10] !! 3 -- 4
|
||||
|
||||
-- Haskell unterstützt unendliche Listen!
|
||||
@ -282,7 +284,7 @@ for [0..5] $ \i -> show i
|
||||
-- wir hätten sie auch so benutzen können:
|
||||
for [0..5] show
|
||||
|
||||
-- foldl oder foldr reduziren Listen auf einen Wert.
|
||||
-- foldl oder foldr reduzieren Listen auf einen Wert.
|
||||
-- foldl <Funktion> <initialer Wert> <Liste>
|
||||
foldl (\x y -> 2*x + y) 4 [1,2,3] -- 43
|
||||
|
||||
@ -345,7 +347,7 @@ main' = interact countLines
|
||||
|
||||
-- Man kann den Typ `IO ()` als Repräsentation einer Sequenz von
|
||||
-- Aktionen sehen, die der Computer abarbeiten muss.
|
||||
-- Wie bei einem Programm das in einer Imperativen Sprache geschreiben wurde.
|
||||
-- Wie bei einem Programm das in einer Imperativen Sprache geschrieben wurde.
|
||||
-- Mit der `do` Notation können Aktionen verbunden werden.
|
||||
|
||||
sayHello :: IO ()
|
||||
@ -419,7 +421,6 @@ foo :: Integer
|
||||
What is your name?
|
||||
Friend!
|
||||
Hello, Friend!
|
||||
|
||||
```
|
||||
|
||||
Es gibt noch viel mehr in Haskell, wie zum Beispiel Typklassen und Monaden.
|
||||
|
@ -10,7 +10,7 @@ lang: de-de
|
||||
|
||||
HTML steht für HyperText Markup Language (Hypertext-Auszeichnungssprache).
|
||||
Sie ist eine Sprache, um Seiten für das World Wide Web zu schreiben.
|
||||
Es ist eine Auszeichnugssprache, die es uns ermöglicht Webseiten mithilfe des Codes zu schreiben, der kennzeichnet wie Text und Daten angezeigt werden sollen. Eigentlich sind HTML Dateien nur einfache Textdateien.
|
||||
Es ist eine Auszeichnungssprache, die es uns ermöglicht Webseiten mithilfe des Codes zu schreiben, der kennzeichnet wie Text und Daten angezeigt werden sollen. Eigentlich sind HTML Dateien nur einfache Textdateien.
|
||||
Was sind das für Auszeichnungen? Es ist eine Methode, um die Daten der Website zu organisieren mithilfe von Start- und Endtags.
|
||||
Diese Auszeichnung dient dazu dem Text Bedeutung zu geben, welchen sie umschließt.
|
||||
Wie viele andere Computersprachen auch, besitzt HTML viele Versionen. Wir werden hier über HTML5 reden.
|
||||
@ -65,7 +65,7 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben
|
||||
</head>
|
||||
|
||||
<!-- Nach dem <head> Bereich findet sich der <body> Tag -->
|
||||
<!-- Bis zu diesem Punkt wird nichts im Browerfenster angezeigt. -->
|
||||
<!-- Bis zu diesem Punkt wird nichts im Browserfenster angezeigt. -->
|
||||
<!-- Wir müssen den Body mit dem Inhalt füllen, der angezeigt werden soll. -->
|
||||
|
||||
<body>
|
||||
@ -95,7 +95,7 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben
|
||||
<table> <!-- Wir öffnen ein <table> Element. -->
|
||||
<tr> <!-- <tr> erlaubt es uns, Reihen zu erstellen. -->
|
||||
<th>Erster Tabellenkopf</th> <!-- <th> erlaubt es uns, der Tabelle einen Titel zu geben. -->
|
||||
<th>Zweiter Tabllenkopf</th>
|
||||
<th>Zweiter Tabellenkopf</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Erste Zeile, erste Spalte</td> <!-- <td> erlaubt es, eine Tabellenzelle zu erstellen. -->
|
||||
@ -106,7 +106,6 @@ Dieser Artikel ist bedacht darauf, nur HTML Syntax und nützliche Tipps zu geben
|
||||
<td>Zweite Zeile, zweite Spalte</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
```
|
||||
|
||||
## Verwendung
|
||||
|
@ -125,9 +125,9 @@ public class LearnJavaDe {
|
||||
|
||||
// Weitere nennenswerte Typen
|
||||
// ArrayLists - Ähnlich Arrays, allerdings werden mehr Funktionen geboten,
|
||||
// ebenso ist die Arraygröße verwänderbar
|
||||
// ebenso ist die Arraygröße veränderbar
|
||||
// LinkedLists - Implementierung einer doppelt verlinkten Liste.
|
||||
// Alle Operationen funktioneren so, wie es von einer doppelt verlinkten Liste erwartet wird.
|
||||
// Alle Operationen funktionieren so, wie es von einer doppelt verlinkten Liste erwartet wird.
|
||||
// Weitere Informationen: https://de.wikipedia.org/wiki/Liste_(Datenstruktur)#Doppelt_.28mehrfach.29_verkettete_Liste
|
||||
// Maps - Eine Sammlung von Objekten, welche eine Verknüpfung von Schlüsseln zu Werten (key => value) vornimmt.
|
||||
// Eine Map kann keine Duplikate enthalten; Jeder Schlüssel kann genau einen Wert beinhalten.
|
||||
@ -173,7 +173,7 @@ public class LearnJavaDe {
|
||||
// Inkrementierungen
|
||||
int i = 0;
|
||||
System.out.println("\n->Inc/Dec-rementierung");
|
||||
// Die ++ und -- operatoren inkrementieren und dekrementieren jeweils um 1.
|
||||
// Die ++ und -- Operatoren inkrementieren und dekrementieren jeweils um 1.
|
||||
// Werden sie vor die Variable gesetzt, ink-/dekrementieren sie und geben anschließend ihren Wert zurück.
|
||||
// Hinter der Variable geben sie ihren Wert zurück und ändern ihn anschließend.
|
||||
System.out.println(i++); // i = 1, schreibt 0 (post-increment)
|
||||
@ -284,7 +284,7 @@ public class LearnJavaDe {
|
||||
// String
|
||||
|
||||
// Tpe-Casting
|
||||
// Java Objekte können benfalls konvertiert werden, hierbei gibt es vielfältige Konzepte.
|
||||
// Java Objekte können ebenfalls konvertiert werden, hierbei gibt es vielfältige Konzepte.
|
||||
// Weitere Informationen finden sich hier (englisch):
|
||||
// http://docs.oracle.com/javase/tutorial/java/IandI/subclasses.html
|
||||
|
||||
@ -311,7 +311,7 @@ public class LearnJavaDe {
|
||||
} // Ende der LearnJavaDe Klasse
|
||||
|
||||
|
||||
// In einer .java-Datei können zusätzliche nicht öffentliche (non-public) äüßere Klassen vorhanden sein.
|
||||
// In einer .java-Datei können zusätzliche nicht öffentliche (non-public) äußere Klassen vorhanden sein.
|
||||
|
||||
|
||||
// Syntax der Klassendeklaration:
|
||||
@ -490,7 +490,7 @@ Für tiefergreifende Fragen ist Google der beste Startpunkt.
|
||||
|
||||
* [Head First Java](http://www.headfirstlabs.com/books/hfjava/)
|
||||
|
||||
* [Thinking in Java](http://www.mindview.net/Books/TIJ/)
|
||||
* [Thinking in Java](https://www.amazon.com/Thinking-Java-4th-Bruce-Eckel/dp/0131872486/)
|
||||
|
||||
* [Objects First with Java](http://www.amazon.com/Objects-First-Java-Practical-Introduction/dp/0132492660)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -14,7 +14,7 @@ Dokument das vermutlich einfachste "Learn X in Y Minutes" werden.
|
||||
|
||||
In seiner grundlegenden Form hat JSON keine eigentlichen Kommentare. Dennoch
|
||||
akzeptieren die meisten Parser Kommentare in C-Syntax (`//`, `/* */`). Dennoch
|
||||
soll für dieses Dokument nur 100% gültiges JSON verwendet werden, weshalbt keine
|
||||
soll für dieses Dokument nur 100 % gültiges JSON verwendet werden, weshalb keine
|
||||
Kommentare verwendet werden. Glücklicherweise ist das nachfolgende Dokument
|
||||
selbsterklärend.
|
||||
|
||||
|
@ -57,7 +57,7 @@ filename: latex-de.tex
|
||||
% LaTeX für uns eine Titelseite generieren
|
||||
\maketitle
|
||||
|
||||
% Die meisten Paper haben ein Abstract. LaTeX bietet dafür einen vorgefertigen Befehl an.
|
||||
% Die meisten Paper haben ein Abstract. LaTeX bietet dafür einen vorgefertigten Befehl an.
|
||||
% Das Abstract sollte in der logischen Reihenfolge, also nach dem Titel, aber vor dem
|
||||
% Inhalt erscheinen.
|
||||
% Dieser Befehl ist in den Dokumentenklassen article und report verfügbar.
|
||||
@ -240,6 +240,7 @@ Das war's erst mal!
|
||||
% Dokument beenden
|
||||
\end{document}
|
||||
```
|
||||
|
||||
## Mehr Informationen über LateX
|
||||
|
||||
* Das tolle LaTeX wikibook: [https://de.wikibooks.org/wiki/LaTeX-Kompendium](https://de.wikibooks.org/wiki/LaTeX-Kompendium)
|
||||
|
@ -21,7 +21,7 @@ lang: de-de
|
||||
|
||||
num = 42 -- Alle Nummern sind vom Typ: Double.
|
||||
-- Werd nicht nervös, 64-Bit Double haben 52 Bits zum Speichern von exakten
|
||||
-- Ganzzahlen; Maschinen-Genauigkeit ist kein Problem für Ganzzahlen kleiner als
|
||||
-- Ganzzahlen; Maschinen-Genauigkeit ist kein Problem für Ganzzahlen kleiner als
|
||||
-- 52 Bit.
|
||||
|
||||
s = 'walternate' -- Zeichenketten sind unveränderlich, wie bei Python.
|
||||
@ -29,11 +29,11 @@ t = "Doppelte Anführungszeichen sind auch OK"
|
||||
u = [[ Doppelte eckige Klammern
|
||||
beginnen und beenden
|
||||
mehrzeilige Zeichenketten.]]
|
||||
t = nil -- Undefineren von t; Lua hat einen Garbage Collection.
|
||||
t = nil -- Undefinieren von t; Lua hat einen Garbage Collection.
|
||||
|
||||
-- Blöcke werden durch Schlüsselwörter wie do/end markiert:
|
||||
while num < 50 do
|
||||
num = num + 1 -- Es gibt Keine Operatoren wie ++ oder +=
|
||||
num = num + 1 -- Es gibt keine Operatoren wie ++ oder +=
|
||||
end
|
||||
|
||||
-- If Bedingungen:
|
||||
@ -72,7 +72,7 @@ for i = 1, 100 do -- Ein Bereich inkludiert beide Enden.
|
||||
karlSum = karlSum + i
|
||||
end
|
||||
|
||||
-- Verwende "100, 1, -1" als Breich für Countdowns:
|
||||
-- Verwende "100, 1, -1" als Bereich für Countdowns:
|
||||
fredSum = 0
|
||||
for j = 100, 1, -1 do fredSum = fredSum + j end
|
||||
|
||||
@ -161,7 +161,7 @@ print(t.key1) -- Ausgabe 'value1'.
|
||||
t.newKey = {} -- Neues Schlüssel/Wert-Paar hinzufügen.
|
||||
t.key2 = nil -- key2 aus der Tabelle entfernen.
|
||||
|
||||
-- Literale notation für jeden (nicht-nil) Wert als Schlüssel:
|
||||
-- Literale Notation für jeden (nicht-nil) Wert als Schlüssel:
|
||||
u = {['@!#'] = 'qbert', [{}] = 1729, [6.28] = 'tau'}
|
||||
print(u[6.28]) -- Ausgabe "tau"
|
||||
|
||||
@ -171,7 +171,7 @@ a = u['@!#'] -- Nun ist a = 'qbert'.
|
||||
b = u[{}] -- Wir würden 1729 erwarten, aber es ist nil:
|
||||
-- b = nil weil der Lookup fehlschlägt. Er schlägt Fehl, weil der Schlüssel
|
||||
-- den wir verwendet haben nicht das gleiche Objekt ist das wir verwendet
|
||||
-- haben um den original Wert zu speichern. Zahlen und Zeichnkette sind daher
|
||||
-- haben um den original Wert zu speichern. Zahlen und Zeichenkette sind daher
|
||||
-- die praktischeren Schlüssel.
|
||||
|
||||
-- Eine Funktion mit nur einem Tabellen-Parameter benötigt keine Klammern.
|
||||
@ -230,7 +230,7 @@ s = f1 + f2 -- Rufe __add(f1, f2) vom der Metatabelle von f1 auf.
|
||||
|
||||
-- Die nächste Zeile schlägt fehl weil s keine Metatabelle hat:
|
||||
-- t = s + s
|
||||
-- Mihilfe von Klassen ähnlichen Mustern kann das gelöst werden.
|
||||
-- Mithilfe von Klassen ähnlichen Mustern kann das gelöst werden.
|
||||
-- Siehe weiter unten.
|
||||
|
||||
-- Ein __index einer Metatabelle überlädt Punkt-Lookups:
|
||||
@ -269,10 +269,10 @@ eatenBy = myFavs.animal -- Funktioniert dank Metatabelle!
|
||||
-- 3.2 Klassen-Artige Tabellen und Vererbung.
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
-- Klassen sind in Lua nicht eingebaut. Es gibt verschieden Wege sie mithilfe
|
||||
-- Klassen sind in Lua nicht eingebaut. Es gibt verschiedene Wege sie mithilfe
|
||||
-- von Tabellen und Metatabellen zu erzeugen.
|
||||
|
||||
-- Die Erklärund des Beispiels erfolgt unterhalb.
|
||||
-- Die Erklärung des Beispiels erfolgt unterhalb.
|
||||
|
||||
Dog = {} -- 1.
|
||||
|
||||
@ -294,7 +294,7 @@ mrDog:makeSound() -- 'I say woof' -- 8.
|
||||
-- "function tablename.fn(self, ...)", Der : fügt nur ein Argument namens
|
||||
-- self hinzu. Siehe 7 & 8 um zu sehen wie self seinen Wert bekommt.
|
||||
-- 3. newObj wird eine Instanz von Dog.
|
||||
-- 4. "self" ist die zu Instanzierende Klasse. Meistern ist self = Dog, aber
|
||||
-- 4. "self" ist die zu instanziierende Klasse. Meistern ist self = Dog, aber
|
||||
-- dies kann durch Vererbung geändert werden. newObj bekommt die Funktionen
|
||||
-- von self wenn wir die Metatabelle von newObj und __index von self auf
|
||||
-- self setzen.
|
||||
@ -400,27 +400,26 @@ g = loadstring('print(343)') -- Gibt eine Funktion zurück..
|
||||
g() -- Ausgabe 343; Vorher kam keine Ausgabe.
|
||||
|
||||
--]]
|
||||
|
||||
```
|
||||
|
||||
## Referenzen
|
||||
|
||||
Ich war so begeistert Lua zu lernen, damit ich Spiele mit <a href="http://love2d.org/">Love 2D game engine</a> programmieren konnte.
|
||||
Ich war so begeistert Lua zu lernen, damit ich Spiele mit [LÖVE game engine](http://love2d.org/) programmieren konnte.
|
||||
|
||||
Ich habe angefangen mit <a href="http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/">BlackBulletIV's Lua for programmers</a>.
|
||||
Danach habe ich das offizielle Lua Buch gelesen: <a href="http://www.lua.org/pil/contents.html">Programming in Lua</a>
|
||||
Ich habe angefangen mit [BlackBulletIV's Lua for programmers](http://nova-fusion.com/2012/08/27/lua-for-programmers-part-1/).
|
||||
Danach habe ich das offizielle Lua Buch gelesen: [Programming in Lua](http://www.lua.org/pil/contents.html)
|
||||
|
||||
Es kann auch hilfreich sein hier vorbeizuschauen: <a href="http://lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf">Lua short
|
||||
reference</a>
|
||||
Es kann auch hilfreich sein hier vorbeizuschauen: [Lua short reference](http://lua-users.org/files/wiki_insecure/users/thomasl/luarefv51.pdf)
|
||||
|
||||
Wichtige Themen die hier nicht angesprochen wurden; die Standard-Bibliotheken:
|
||||
|
||||
* <a href="http://lua-users.org/wiki/StringLibraryTutorial">string library</a>
|
||||
* <a href="http://lua-users.org/wiki/TableLibraryTutorial">table library</a>
|
||||
* <a href="http://lua-users.org/wiki/MathLibraryTutorial">math library</a>
|
||||
* <a href="http://lua-users.org/wiki/IoLibraryTutorial">io library</a>
|
||||
* <a href="http://lua-users.org/wiki/OsLibraryTutorial">os library</a>
|
||||
* [`string` library](http://lua-users.org/wiki/StringLibraryTutorial)
|
||||
* [`table` library](http://lua-users.org/wiki/TableLibraryTutorial)
|
||||
* [`math` library](http://lua-users.org/wiki/MathLibraryTutorial)
|
||||
* [`io` library](http://lua-users.org/wiki/IoLibraryTutorial)
|
||||
* [`os` library](http://lua-users.org/wiki/OsLibraryTutorial)
|
||||
|
||||
Übrigends, die gesamte Datei ist gültiges Lua. Speichere sie als learn.lua und
|
||||
starte sie als "lua learn.lua" !
|
||||
Übrigens, die gesamte Datei ist gültiges Lua. Speichere sie als learn.lua und
|
||||
starte sie als "`lua learn.lua`" !
|
||||
|
||||
Die Erstfassung ist von tylerneylon.com, und ist auch hier verfügbar: <a href="https://gist.github.com/tylerneylon/5853042">github gist</a>. Viel Spaß mit Lua!
|
||||
Die Erstfassung ist von tylerneylon.com, und ist auch hier verfügbar: [GitHub gist](https://gist.github.com/tylerneylon/5853042). Viel Spaß mit Lua!
|
||||
|
@ -1,263 +1,262 @@
|
||||
---
|
||||
category: tool
|
||||
tool: make
|
||||
contributors:
|
||||
- ["Robert Steed", "https://github.com/robochat"]
|
||||
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
||||
translators:
|
||||
- ["Martin Schimandl", "https://github.com/Git-Jiro"]
|
||||
filename: Makefile-de
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Eine Makefile definiert einen Graphen von Regeln um ein Ziel (oder Ziele)
|
||||
zu erzeugen. Es dient dazu, die geringste Menge an Arbeit zu verrichten um
|
||||
ein Ziel in Einklang mit dem Quellcode zu bringen. Make wurde berühmterweise
|
||||
von Stuart Feldman 1976 übers Wochenende geschrieben. Make ist noch immer
|
||||
sehr verbreitet (vorallem im Unix Umfeld) obwohl es bereits sehr viel
|
||||
Konkurrenz und Kritik zu Make gibt.
|
||||
|
||||
Es gibt eine Vielzahl an Varianten von Make, dieser Artikel beschäftigt sich
|
||||
mit der Version GNU Make. Diese Version ist Standard auf Linux.
|
||||
|
||||
```make
|
||||
|
||||
# Kommentare können so geschrieben werden.
|
||||
|
||||
# Dateien sollten Makefile heißen, denn dann können sie als `make <ziel>`
|
||||
# aufgerufen werden. Ansonsten muss `make -f "dateiname" <ziel>` verwendet
|
||||
# werden.
|
||||
|
||||
# Warnung - Es sollten nur TABULATOREN zur Einrückung im Makefile verwendet
|
||||
# werden. Niemals Leerzeichen!
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Grundlagen
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Eine Regel - Diese Regel wird nur abgearbeitet wenn die Datei file0.txt
|
||||
# nicht existiert.
|
||||
file0.txt:
|
||||
echo "foo" > file0.txt
|
||||
# Selbst Kommentare in der 'Rezept' Sektion werden an die Shell
|
||||
# weitergegeben. Versuche `make file0.txt` oder einfach `make`
|
||||
# die erste Regel ist die Standard-Regel.
|
||||
|
||||
|
||||
# Diese Regel wird nur abgearbeitet, wenn file0.txt aktueller als file1.txt ist.
|
||||
file1.txt: file0.txt
|
||||
cat file0.txt > file1.txt
|
||||
# Verwende die selben Quoting-Regeln wie die Shell
|
||||
@cat file0.txt >> file1.txt
|
||||
# @ unterdrückt die Ausgabe des Befehls an stdout.
|
||||
-@echo 'hello'
|
||||
# - bedeutet, dass Make die Abarbeitung fortsetzt auch wenn Fehler
|
||||
# passieren.
|
||||
# Versuche `make file1.txt` auf der Kommandozeile.
|
||||
|
||||
# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
|
||||
file2.txt file3.txt: file0.txt file1.txt
|
||||
touch file2.txt
|
||||
touch file3.txt
|
||||
|
||||
# Make wird sich beschweren, wenn es mehrere Rezepte für die gleiche Regel gibt.
|
||||
# Leere Rezepte zählen nicht und können dazu verwendet werden weitere
|
||||
# Voraussetzungen hinzuzufügen.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Phony-Ziele
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Ein Phony-Ziel ist ein Ziel, das keine Datei ist.
|
||||
# Es wird nie aktuell sein, daher wird Make immer versuchen, es abzuarbeiten
|
||||
all: maker process
|
||||
|
||||
# Es ist erlaubt Dinge ausserhalb der Reihenfolge zu deklarieren.
|
||||
maker:
|
||||
touch ex0.txt ex1.txt
|
||||
|
||||
# Um das Fehlschlagen von Phony-Regeln zu vermeiden wenn eine echte Datei den
|
||||
# selben namen wie ein Phony-Ziel hat:
|
||||
.PHONY: all maker process
|
||||
# Das ist ein spezielles Ziel. Es gibt noch ein paar mehr davon.
|
||||
|
||||
# Eine Regel mit einem Phony-Ziel als Voraussetzung wird immer abgearbeitet
|
||||
ex0.txt ex1.txt: maker
|
||||
|
||||
# Häufige Phony-Ziele sind: all make clean install ...
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Automatische Variablen & Wildcards
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
process: file*.txt # Eine Wildcard um Dateinamen zu vergleichen
|
||||
@echo $^ # $^ ist eine Variable die eine Liste aller
|
||||
# Voraussetzungen enthält.
|
||||
@echo $@ # Namen des Ziels ausgeben.
|
||||
#(Bei mehreren Ziel-Regeln enthält $@ den Verursacher der Abarbeitung
|
||||
#der Regel.)
|
||||
@echo $< # Die erste Voraussetzung aus der Liste
|
||||
@echo $? # Nur die Voraussetzungen, die nicht aktuell sind.
|
||||
@echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie Üblich)
|
||||
#@echo $| # Alle 'order only' Voraussetzungen
|
||||
|
||||
# Selbst wenn wir die Voraussetzungen der Regel aufteilen, $^ wird sie finden.
|
||||
process: ex1.txt file0.txt
|
||||
# ex1.txt wird gefunden werden, aber file0.txt wird dedupliziert.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Muster
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Mit Mustern kann man make beibringen wie Dateien in andere Dateien
|
||||
# umgewandelt werden.
|
||||
|
||||
%.png: %.svg
|
||||
inkscape --export-png $^
|
||||
|
||||
# Muster-Vergleichs-Regeln werden nur abgearbeitet, wenn make entscheidet das
|
||||
# Ziel zu erzeugen
|
||||
|
||||
# Verzeichnis-Pfade werden normalerweise bei Muster-Vergleichs-Regeln ignoriert.
|
||||
# Aber make wird versuchen die am besten passende Regel zu verwenden.
|
||||
small/%.png: %.svg
|
||||
inkscape --export-png --export-dpi 30 $^
|
||||
|
||||
# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden, die es
|
||||
# findet.
|
||||
%.png: %.svg
|
||||
@echo this rule is chosen
|
||||
|
||||
# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden, die das
|
||||
# Ziel erzeugen kann.
|
||||
%.png: %.ps
|
||||
@echo this rule is not chosen if *.svg and *.ps are both present
|
||||
|
||||
# Make hat bereits ein paar eingebaute Muster-Vergleichs-Regelen. Zum Beispiel
|
||||
# weiß Make wie man aus *.c Dateien *.o Dateien erzeugt.
|
||||
|
||||
# Ältere Versionen von Make verwenden möglicherweise Suffix-Regeln anstatt
|
||||
# Muster-Vergleichs-Regeln.
|
||||
.png.ps:
|
||||
@echo this rule is similar to a pattern rule.
|
||||
|
||||
# Aktivieren der Suffix-Regel
|
||||
.SUFFIXES: .png
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Variablen
|
||||
#-----------------------------------------------------------------------
|
||||
# auch Makros genannt.
|
||||
|
||||
# Variablen sind im Grunde genommen Zeichenketten-Typen.
|
||||
|
||||
name = Ted
|
||||
name2="Sarah"
|
||||
|
||||
echo:
|
||||
@echo $(name)
|
||||
@echo ${name2}
|
||||
@echo $name # Das funktioniert nicht, wird als $(n)ame behandelt.
|
||||
@echo $(name3) # Unbekannte Variablen werden als leere Zeichenketten behandelt.
|
||||
|
||||
# Es git 4 Stellen um Variablen zu setzen.
|
||||
# In Reihenfolge der Priorität von höchster zu niedrigster:
|
||||
# 1: Befehls-Zeilen Argumente
|
||||
# 2: Makefile
|
||||
# 3: Shell Umbebungs-Variablen - Make importiert diese automatisch.
|
||||
# 3: MAke hat einige vordefinierte Variablen.
|
||||
|
||||
name4 ?= Jean
|
||||
# Setze die Variable nur wenn es eine gleichnamige Umgebungs-Variable noch
|
||||
# nicht gibt.
|
||||
|
||||
override name5 = David
|
||||
# Verhindert, dass Kommando-Zeilen Argumente diese Variable ändern können.
|
||||
|
||||
name4 +=grey
|
||||
# Werte an eine Variable anhängen (inkludiert Leerzeichen).
|
||||
|
||||
# Muster-Spezifische Variablen Werte (GNU Erweiterung).
|
||||
echo: name2 = Sara # Wahr innerhalb der passenden Regel und auch innerhalb
|
||||
# rekursiver Voraussetzungen (ausser wenn es den Graphen zerstören
|
||||
# kann, wenn es zu kompilizert wird!)
|
||||
|
||||
# Ein paar Variablen, die von Make automatisch definiert werden.
|
||||
echo_inbuilt:
|
||||
echo $(CC)
|
||||
echo ${CXX}
|
||||
echo $(FC)
|
||||
echo ${CFLAGS}
|
||||
echo $(CPPFLAGS)
|
||||
echo ${CXXFLAGS}
|
||||
echo $(LDFLAGS)
|
||||
echo ${LDLIBS}
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Variablen 2
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Der erste Typ von Variablen wird bei jeder Verwendung ausgewertet.
|
||||
# Das kann aufwendig sein, daher exisitert ein zweiter Typ von Variablen.
|
||||
# Diese werden nur einmal ausgewertet. (Das ist eine GNU make Erweiterung)
|
||||
|
||||
var := hello
|
||||
var2 ::= $(var) hello
|
||||
#:= und ::= sind äquivalent.
|
||||
|
||||
# Diese Variablen werden prozedural ausgwertet (in der Reihenfolge in der sie
|
||||
# auftauchen), die stehen daher im wiederspruch zum Rest der Sprache!
|
||||
|
||||
# Das funktioniert nicht
|
||||
var3 ::= $(var4) and good luck
|
||||
var4 ::= good night
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Funktionen
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Make verfügt über eine Vielzahl von Funktionen.
|
||||
|
||||
sourcefiles = $(wildcard *.c */*.c)
|
||||
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
||||
|
||||
# Das Format ist $(func arg0,arg1,arg2...)
|
||||
|
||||
# Ein paar Beispiele
|
||||
ls: * src/*
|
||||
@echo $(filter %.txt, $^)
|
||||
@echo $(notdir $^)
|
||||
@echo $(join $(dir $^),$(notdir $^))
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Direktiven
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Inkludiere andere Makefile, sehr praktisch für platformspezifischen Code
|
||||
include foo.mk
|
||||
|
||||
sport = tennis
|
||||
# Konditionale kompiliereung
|
||||
report:
|
||||
ifeq ($(sport),tennis)
|
||||
@echo 'game, set, match'
|
||||
else
|
||||
@echo "They think it's all over; it is now"
|
||||
endif
|
||||
|
||||
# Es gibt auch ifneq, ifdef, ifndef
|
||||
|
||||
foo = true
|
||||
|
||||
ifdef $(foo)
|
||||
bar = 'hello'
|
||||
endif
|
||||
```
|
||||
|
||||
|
||||
### Mehr Resourcen
|
||||
|
||||
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
|
||||
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
|
||||
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
|
||||
|
||||
---
|
||||
category: tool
|
||||
tool: make
|
||||
contributors:
|
||||
- ["Robert Steed", "https://github.com/robochat"]
|
||||
- ["Stephan Fuhrmann", "https://github.com/sfuhrm"]
|
||||
translators:
|
||||
- ["Martin Schimandl", "https://github.com/Git-Jiro"]
|
||||
filename: Makefile-de
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Eine Makefile definiert einen Graphen von Regeln um ein Ziel (oder Ziele)
|
||||
zu erzeugen. Es dient dazu, die geringste Menge an Arbeit zu verrichten um
|
||||
ein Ziel in Einklang mit dem Quellcode zu bringen. Make wurde berühmterweise
|
||||
von Stuart Feldman 1976 übers Wochenende geschrieben. Make ist noch immer
|
||||
sehr verbreitet (vorallem im Unix Umfeld) obwohl es bereits sehr viel
|
||||
Konkurrenz und Kritik zu Make gibt.
|
||||
|
||||
Es gibt eine Vielzahl an Varianten von Make, dieser Artikel beschäftigt sich
|
||||
mit der Version GNU Make. Diese Version ist Standard auf Linux.
|
||||
|
||||
```make
|
||||
# Kommentare können so geschrieben werden.
|
||||
|
||||
# Dateien sollten Makefile heißen, denn dann können sie als `make <ziel>`
|
||||
# aufgerufen werden. Ansonsten muss `make -f "dateiname" <ziel>` verwendet
|
||||
# werden.
|
||||
|
||||
# Warnung - Es sollten nur TABULATOREN zur Einrückung im Makefile verwendet
|
||||
# werden. Niemals Leerzeichen!
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Grundlagen
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Eine Regel - Diese Regel wird nur abgearbeitet, wenn die Datei file0.txt
|
||||
# nicht existiert.
|
||||
file0.txt:
|
||||
echo "foo" > file0.txt
|
||||
# Selbst Kommentare in der 'Rezept' Sektion werden an die Shell
|
||||
# weitergegeben. Versuche `make file0.txt` oder einfach `make`
|
||||
# die erste Regel ist die Standard-Regel.
|
||||
|
||||
|
||||
# Diese Regel wird nur abgearbeitet, wenn file0.txt aktueller als file1.txt ist.
|
||||
file1.txt: file0.txt
|
||||
cat file0.txt > file1.txt
|
||||
# Verwende die selben Quoting-Regeln wie die Shell
|
||||
@cat file0.txt >> file1.txt
|
||||
# @ unterdrückt die Ausgabe des Befehls an stdout.
|
||||
-@echo 'hello'
|
||||
# - bedeutet, dass Make die Abarbeitung fortsetzt, auch wenn Fehler
|
||||
# passieren.
|
||||
# Versuche `make file1.txt` auf der Kommandozeile.
|
||||
|
||||
# Eine Regel kann mehrere Ziele und mehrere Voraussetzungen haben.
|
||||
file2.txt file3.txt: file0.txt file1.txt
|
||||
touch file2.txt
|
||||
touch file3.txt
|
||||
|
||||
# Make wird sich beschweren, wenn es mehrere Rezepte für die gleiche Regel gibt.
|
||||
# Leere Rezepte zählen nicht und können dazu verwendet werden weitere
|
||||
# Voraussetzungen hinzuzufügen.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Phony-Ziele
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Ein Phony-Ziel ist ein Ziel, das keine Datei ist.
|
||||
# Es wird nie aktuell sein, daher wird Make immer versuchen, es abzuarbeiten
|
||||
all: maker process
|
||||
|
||||
# Es ist erlaubt Dinge außerhalb der Reihenfolge zu deklarieren.
|
||||
maker:
|
||||
touch ex0.txt ex1.txt
|
||||
|
||||
# Um das Fehlschlagen von Phony-Regeln zu vermeiden wenn eine echte Datei den
|
||||
# selben Namen wie ein Phony-Ziel hat:
|
||||
.PHONY: all maker process
|
||||
# Das ist ein spezielles Ziel. Es gibt noch ein paar mehr davon.
|
||||
|
||||
# Eine Regel mit einem Phony-Ziel als Voraussetzung wird immer abgearbeitet
|
||||
ex0.txt ex1.txt: maker
|
||||
|
||||
# Häufige Phony-Ziele sind: all make clean install ...
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Automatische Variablen & Wildcards
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
process: file*.txt # Eine Wildcard um Dateinamen zu vergleichen
|
||||
@echo $^ # $^ ist eine Variable die eine Liste aller
|
||||
# Voraussetzungen enthält.
|
||||
@echo $@ # Namen des Ziels ausgeben.
|
||||
#(Bei mehreren Ziel-Regeln enthält $@ den Verursacher der Abarbeitung
|
||||
#der Regel.)
|
||||
@echo $< # Die erste Voraussetzung aus der Liste
|
||||
@echo $? # Nur die Voraussetzungen, die nicht aktuell sind.
|
||||
@echo $+ # Alle Voraussetzungen inklusive Duplikate (nicht wie üblich)
|
||||
#@echo $| # Alle 'order only' Voraussetzungen
|
||||
|
||||
# Selbst wenn wir die Voraussetzungen der Regel aufteilen, $^ wird sie finden.
|
||||
process: ex1.txt file0.txt
|
||||
# ex1.txt wird gefunden werden, aber file0.txt wird dedupliziert.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Muster
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Mit Mustern kann man make beibringen wie Dateien in andere Dateien
|
||||
# umgewandelt werden.
|
||||
|
||||
%.png: %.svg
|
||||
inkscape --export-png $^
|
||||
|
||||
# Muster-Vergleichs-Regeln werden nur abgearbeitet, wenn make entscheidet das
|
||||
# Ziel zu erzeugen
|
||||
|
||||
# Verzeichnis-Pfade werden normalerweise bei Muster-Vergleichs-Regeln ignoriert.
|
||||
# Aber make wird versuchen, die am besten passende Regel zu verwenden.
|
||||
small/%.png: %.svg
|
||||
inkscape --export-png --export-dpi 30 $^
|
||||
|
||||
# Make wird die letzte Version einer Muster-Vergleichs-Regel verwenden, die es
|
||||
# findet.
|
||||
%.png: %.svg
|
||||
@echo this rule is chosen
|
||||
|
||||
# Allerdings wird make die erste Muster-Vergleicher-Regel verwenden, die das
|
||||
# Ziel erzeugen kann.
|
||||
%.png: %.ps
|
||||
@echo this rule is not chosen if *.svg and *.ps are both present
|
||||
|
||||
# Make hat bereits ein paar eingebaute Muster-Vergleichs-Regeln. Zum Beispiel
|
||||
# weiß Make wie man aus *.c Dateien *.o Dateien erzeugt.
|
||||
|
||||
# Ältere Versionen von Make verwenden möglicherweise Suffix-Regeln anstatt
|
||||
# Muster-Vergleichs-Regeln.
|
||||
.png.ps:
|
||||
@echo this rule is similar to a pattern rule.
|
||||
|
||||
# Aktivieren der Suffix-Regel
|
||||
.SUFFIXES: .png
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Variablen
|
||||
#-----------------------------------------------------------------------
|
||||
# auch Makros genannt.
|
||||
|
||||
# Variablen sind im Grunde genommen Zeichenketten-Typen.
|
||||
|
||||
name = Ted
|
||||
name2="Sarah"
|
||||
|
||||
echo:
|
||||
@echo $(name)
|
||||
@echo ${name2}
|
||||
@echo $name # Das funktioniert nicht, wird als $(n)ame behandelt.
|
||||
@echo $(name3) # Unbekannte Variablen werden als leere Zeichenketten behandelt.
|
||||
|
||||
# Es gibt 4 Stellen um Variablen zu setzen.
|
||||
# In Reihenfolge der Priorität von höchster zu niedrigster:
|
||||
# 1: Befehls-Zeilen Argumente
|
||||
# 2: Makefile
|
||||
# 3: Shell Umgebungs-Variablen - Make importiert diese automatisch.
|
||||
# 3: Make hat einige vordefinierte Variablen.
|
||||
|
||||
name4 ?= Jean
|
||||
# Setze die Variable nur wenn es eine gleichnamige Umgebungs-Variable noch
|
||||
# nicht gibt.
|
||||
|
||||
override name5 = David
|
||||
# Verhindert, dass Kommando-Zeilen Argumente diese Variable ändern können.
|
||||
|
||||
name4 +=grey
|
||||
# Werte an eine Variable anhängen (inkludiert Leerzeichen).
|
||||
|
||||
# Muster-Spezifische Variablen Werte (GNU Erweiterung).
|
||||
echo: name2 = Sara # Wahr innerhalb der passenden Regel und auch innerhalb
|
||||
# rekursiver Voraussetzungen (außer wenn es den Graphen zerstören
|
||||
# kann, wenn es zu kompliziert wird!)
|
||||
|
||||
# Ein paar Variablen, die von Make automatisch definiert werden.
|
||||
echo_inbuilt:
|
||||
echo $(CC)
|
||||
echo ${CXX}
|
||||
echo $(FC)
|
||||
echo ${CFLAGS}
|
||||
echo $(CPPFLAGS)
|
||||
echo ${CXXFLAGS}
|
||||
echo $(LDFLAGS)
|
||||
echo ${LDLIBS}
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Variablen 2
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Der erste Typ von Variablen wird bei jeder Verwendung ausgewertet.
|
||||
# Das kann aufwendig sein, daher existiert ein zweiter Typ von Variablen.
|
||||
# Diese werden nur einmal ausgewertet. (Das ist eine GNU make Erweiterung)
|
||||
|
||||
var := hello
|
||||
var2 ::= $(var) hello
|
||||
#:= und ::= sind äquivalent.
|
||||
|
||||
# Diese Variablen werden prozedural ausgewertet (in der Reihenfolge, in der sie
|
||||
# auftauchen), die stehen daher im Widerspruch zum Rest der Sprache!
|
||||
|
||||
# Das funktioniert nicht
|
||||
var3 ::= $(var4) and good luck
|
||||
var4 ::= good night
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Funktionen
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Make verfügt über eine Vielzahl von Funktionen.
|
||||
|
||||
sourcefiles = $(wildcard *.c */*.c)
|
||||
objectfiles = $(patsubst %.c,%.o,$(sourcefiles))
|
||||
|
||||
# Das Format ist $(func arg0,arg1,arg2...)
|
||||
|
||||
# Ein paar Beispiele
|
||||
ls: * src/*
|
||||
@echo $(filter %.txt, $^)
|
||||
@echo $(notdir $^)
|
||||
@echo $(join $(dir $^),$(notdir $^))
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Direktiven
|
||||
#-----------------------------------------------------------------------
|
||||
|
||||
# Inkludiere andere Makefile, sehr praktisch für plattformspezifischen Code
|
||||
include foo.mk
|
||||
|
||||
sport = tennis
|
||||
# Konditionale Kompilierung
|
||||
report:
|
||||
ifeq ($(sport),tennis)
|
||||
@echo 'game, set, match'
|
||||
else
|
||||
@echo "They think it's all over; it is now"
|
||||
endif
|
||||
|
||||
# Es gibt auch ifneq, ifdef, ifndef
|
||||
|
||||
foo = true
|
||||
|
||||
ifdef $(foo)
|
||||
bar = 'hello'
|
||||
endif
|
||||
```
|
||||
|
||||
|
||||
### Mehr Ressourcen
|
||||
|
||||
+ [gnu make documentation](https://www.gnu.org/software/make/manual/)
|
||||
+ [software carpentry tutorial](http://swcarpentry.github.io/make-novice/)
|
||||
+ learn C the hard way [ex2](http://c.learncodethehardway.org/book/ex2.html) [ex28](http://c.learncodethehardway.org/book/ex28.html)
|
||||
|
||||
|
@ -115,7 +115,7 @@ oder
|
||||
3. Punkt drei
|
||||
|
||||
<!-- Auch wenn es keine gute Idee sein mag: du müsstest die einzelnen Punkte
|
||||
nicht mal korrekt numerieren -->
|
||||
nicht mal korrekt nummerieren -->
|
||||
|
||||
1. Punkt eins
|
||||
1. Punkt zwei
|
||||
@ -148,7 +148,7 @@ indem du eine Zeile mit vier Leerzeichen oder einem Tabulator einrückst -->
|
||||
|
||||
Hermann hatte nicht die leiseste Ahnung, was dieses `go_to()` bedeuten könnte!
|
||||
|
||||
<!-- In "GitHub Flavored Markdown" gibt es für Code nocheinmal eine
|
||||
<!-- In "GitHub Flavored Markdown" gibt es für Code noch einmal eine
|
||||
besondere Syntax -->
|
||||
|
||||
\`\`\`ruby <!-- in "echt" musst du die Backslashes entfernen: ```ruby ! -->
|
||||
@ -223,7 +223,7 @@ voranstellt! -->
|
||||
<http://testwebseite.de/> ist das selbe wie
|
||||
[http://testwebseite.de/](http://testwebseite.de/)
|
||||
|
||||
<!-- Automatische Links für E-Mail-Addressen -->
|
||||
<!-- Automatische Links für E-Mail-Adressen -->
|
||||
|
||||
<foo@bar.com>
|
||||
|
||||
|
@ -16,7 +16,7 @@ Du kannst Nix Ausdrücke evaluieren mithilfe von
|
||||
[nix-instantiate](https://nixos.org/nix/manual/#sec-nix-instantiate)
|
||||
oder [`nix-repl`](https://github.com/edolstra/nix-repl).
|
||||
|
||||
```
|
||||
```nix
|
||||
with builtins; [
|
||||
|
||||
# Kommentare
|
||||
@ -222,7 +222,7 @@ with builtins; [
|
||||
({ a = 1; b = 2; } // { a = 3; c = 4; })
|
||||
#=> { a = 3; b = 2; c = 4; }
|
||||
|
||||
# Das Schlüsselwort rec bezeichenet ein "rekursives Set", in dem sich Attribute
|
||||
# Das Schlüsselwort rec bezeichnet ein "rekursives Set", in dem sich Attribute
|
||||
# aufeinander beziehen können.
|
||||
(let a = 1; in { a = 2; b = a; }.b)
|
||||
#=> 1
|
||||
@ -348,14 +348,8 @@ with builtins; [
|
||||
|
||||
### Weitere Ressourcen
|
||||
|
||||
* [Nix Manual - Nix expression language]
|
||||
(https://nixos.org/nix/manual/#ch-expression-language)
|
||||
|
||||
* [James Fisher - Nix by example - Part 1: The Nix expression language]
|
||||
(https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55)
|
||||
|
||||
* [Susan Potter - Nix Cookbook - Nix By Example]
|
||||
(https://ops.functionalalgebra.com/nix-by-example/)
|
||||
|
||||
* [Rommel Martinez - A Gentle Introduction to the Nix Family]
|
||||
(https://web.archive.org/web/20210121042658/https://ebzzry.io/en/nix/#nix)
|
||||
* [Nix Manual - Nix expression language](https://nixos.org/nix/manual/#ch-expression-language)
|
||||
* [James Fisher - Nix by example - Part 1: The Nix expression language](https://medium.com/@MrJamesFisher/nix-by-example-a0063a1a4c55)
|
||||
* [Susan Potter - Nix Cookbook - Nix By Example](https://ops.functionalalgebra.com/nix-by-example/)
|
||||
* [Zero to Nix - Nix Tutorial](https://zero-to-nix.com/)
|
||||
* [Rommel Martinez - A Gentle Introduction to the Nix Family](https://web.archive.org/web/20210121042658/https://ebzzry.io/en/nix/#nix)
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
category: tool
|
||||
tool: OpenCV
|
||||
category: framework
|
||||
framework: OpenCV
|
||||
filename: learnopencv-de.py
|
||||
contributors:
|
||||
- ["Yogesh Ojha", "http://github.com/yogeshojha"]
|
||||
@ -8,21 +8,20 @@ translators:
|
||||
- ["Dennis Keller", "https://github.com/denniskeller"]
|
||||
lang: de-de
|
||||
---
|
||||
### Opencv
|
||||
|
||||
OpenCV (Open Source Computer Vision) ist eine Bibliothek von Programmierfunktionen,
|
||||
OpenCV (Open Source Computer Vision) ist eine Bibliothek von Programmierfunktionen,
|
||||
die hauptsächlich auf maschinelles Sehen in Echtzeit ausgerichtet ist.
|
||||
Ursprünglich wurde OpenCV von Intel entwickelt. Später wurde es von von
|
||||
Ursprünglich wurde OpenCV von Intel entwickelt. Später wurde es von
|
||||
Willow Garage und dann Itseez (das später von Intel übernommen wurde) unterstützt.
|
||||
OpenCV unterstützt derzeit eine Vielzahl von Sprachen, wie C++, Python, Java uvm.
|
||||
|
||||
#### Installation
|
||||
|
||||
Bitte lese diese Artikel für die Installation von OpenCV auf deinen Computer.
|
||||
Bitte lies diesen Artikel für die Installation von OpenCV auf deinem Computer.
|
||||
|
||||
* Windows Installationsanleitung: [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.html#install-opencv-python-in-windows]()
|
||||
* Mac Installationsanleitung (High Sierra): [https://medium.com/@nuwanprabhath/installing-opencv-in-macos-high-sierra-for-python-3-89c79f0a246a]()
|
||||
* Linux Installationsanleitung (Ubuntu 18.04): [https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv]()
|
||||
* [Windows Installationsanleitung](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_setup/py_setup_in_windows/py_setup_in_windows.html#install-opencv-python-in-windows)
|
||||
* [Mac Installationsanleitung](https://medium.com/@nuwanprabhath/installing-opencv-in-macos-high-sierra-for-python-3-89c79f0a246a) (High Sierra)
|
||||
* [Linux Installationsanleitung](https://www.pyimagesearch.com/2018/05/28/ubuntu-18-04-how-to-install-opencv) (Ubuntu 18.04)
|
||||
|
||||
### Hier werden wir uns auf die Pythonimplementierung von OpenCV konzentrieren.
|
||||
|
||||
@ -33,28 +32,28 @@ img = cv2.imread('Katze.jpg')
|
||||
|
||||
# Bild darstellen
|
||||
# Die imshow() Funktion wird verwendet um das Display darzustellen.
|
||||
cv2.imshow('Image',img)
|
||||
cv2.imshow('Image', img)
|
||||
# Das erste Argument ist der Titel des Fensters und der zweite Parameter ist das Bild
|
||||
# Wenn du den Fehler Object Type None bekommst ist eventuell dein Bildpfad falsch.
|
||||
# Wenn du den Fehler Object Type None bekommst, ist eventuell dein Bildpfad falsch.
|
||||
# Bitte überprüfe dann den Pfad des Bildes erneut.
|
||||
cv2.waitKey(0)
|
||||
# waitKey() ist eine Tastaturbindungsfunktion, sie nimmt Argumente in
|
||||
# waitKey() ist eine Tastaturbindungsfunktion, sie nimmt Argumente in
|
||||
# Millisekunden an. Für GUI Ereignisse MUSST du die waitKey() Funktion verwenden.
|
||||
|
||||
# Ein Bild schreiben
|
||||
cv2.imwrite('graueKatze.png',img)
|
||||
# Das erste Arkument ist der Dateiname und das Zweite ist das Bild
|
||||
cv2.imwrite('graueKatze.png', img)
|
||||
# Das erste Argument ist der Dateiname und das zweite ist das Bild
|
||||
|
||||
# Konveriere das Bild zu Graustufen
|
||||
# Konvertiert das Bild zu Graustufen
|
||||
gray_image = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
# Videoaufnahme von der Webcam
|
||||
cap = cv2.VideoCapture(0)
|
||||
# 0 ist deine Kamera, wenn du mehrere Kameras hast musst du deren Id eingeben
|
||||
while(True):
|
||||
while True:
|
||||
# Erfassen von Einzelbildern
|
||||
_, frame = cap.read()
|
||||
cv2.imshow('Frame',frame)
|
||||
cv2.imshow('Frame', frame)
|
||||
# Wenn der Benutzer q drückt -> beenden
|
||||
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||
break
|
||||
@ -63,59 +62,60 @@ cap.release()
|
||||
|
||||
# Wiedergabe von Videos aus einer Datei
|
||||
cap = cv2.VideoCapture('film.mp4')
|
||||
while(cap.isOpened()):
|
||||
while cap.isOpened():
|
||||
_, frame = cap.read()
|
||||
# Das Video in Graustufen abspielen
|
||||
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
|
||||
cv2.imshow('frame',gray)
|
||||
cv2.imshow('frame', gray)
|
||||
if cv2.waitKey(1) & 0xFF == ord('q'):
|
||||
break
|
||||
cap.release()
|
||||
|
||||
# Zeichne eine Linie in OpenCV
|
||||
# cv2.line(img,(x,y),(x1,y1),(color->r,g,b->0 to 255),thickness)
|
||||
cv2.line(img,(0,0),(511,511),(255,0,0),5)
|
||||
# cv2.line(img, (x,y), (x1,y1), (color->r,g,b->0 to 255), thickness)
|
||||
cv2.line(img, (0, 0), (511, 511), (255, 0, 0), 5)
|
||||
|
||||
# Zeichne ein Rechteck
|
||||
# cv2.rectangle(img,(x,y),(x1,y1),(color->r,g,b->0 to 255),thickness)
|
||||
# cv2.rectangle(img, (x,y), (x1,y1), (color->r,g,b->0 to 255), thickness)
|
||||
# thickness = -1 wird zum Füllen des Rechtecks verwendet
|
||||
cv2.rectangle(img,(384,0),(510,128),(0,255,0),3)
|
||||
cv2.rectangle(img, (384, 0), (510, 128), (0, 255, 0), 3)
|
||||
|
||||
# Zeichne ein Kreis
|
||||
cv2.circle(img,(xCenter,yCenter), radius, (color->r,g,b->0 to 255), thickness)
|
||||
cv2.circle(img,(200,90), 100, (0,0,255), -1)
|
||||
# cv2.circle(img, (xCenter,yCenter), radius, (color->r,g,b->0 to 255), thickness)
|
||||
cv2.circle(img, (200, 90), 100, (0, 0, 255), -1)
|
||||
|
||||
# Zeichne eine Ellipse
|
||||
cv2.ellipse(img,(256,256),(100,50),0,0,180,255,-1)
|
||||
cv2.ellipse(img, (256, 256), (100, 50), 0, 0, 180, 255, -1)
|
||||
|
||||
# Text auf Bildern hinzufügen
|
||||
cv2.putText(img,"Hello World!!!", (x,y), cv2.FONT_HERSHEY_SIMPLEX, 2, 255)
|
||||
cv2.putText(img, "Hello World!!!", (x, y), cv2.FONT_HERSHEY_SIMPLEX, 2, 255)
|
||||
|
||||
# Bilder zusammenfüggen
|
||||
# Bilder zusammenfügen
|
||||
img1 = cv2.imread('Katze.png')
|
||||
img2 = cv2.imread('openCV.jpg')
|
||||
dst = cv2.addWeighted(img1,0.5,img2,0.5,0)
|
||||
dst = cv2.addWeighted(img1, 0.5, img2, 0.5, 0)
|
||||
|
||||
# Schwellwertbild
|
||||
# Binäre Schwellenwerte
|
||||
_,thresImg = cv2.threshold(img,127,255,cv2.THRESH_BINARY)
|
||||
# Anpassbare Schwellenwerte
|
||||
adapThres = cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY,11,2)
|
||||
_, thresImg = cv2.threshold(img, 127, 255, cv2.THRESH_BINARY)
|
||||
# Anpassbare Schwellenwerte
|
||||
adapThres = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 11, 2)
|
||||
|
||||
# Weichzeichnung von einem Bild
|
||||
# Gausßscher Weichzeichner
|
||||
blur = cv2.GaussianBlur(img,(5,5),0)
|
||||
# Gaußscher Weichzeichner
|
||||
blur = cv2.GaussianBlur(img, (5, 5), 0)
|
||||
# Rangordnungsfilter
|
||||
medianBlur = cv2.medianBlur(img,5)
|
||||
medianBlur = cv2.medianBlur(img, 5)
|
||||
|
||||
# Canny-Algorithmus
|
||||
img = cv2.imread('Katze.jpg',0)
|
||||
edges = cv2.Canny(img,100,200)
|
||||
img = cv2.imread('Katze.jpg', 0)
|
||||
edges = cv2.Canny(img, 100, 200)
|
||||
|
||||
# Gesichtserkennung mit Haarkaskaden
|
||||
# Lade die Haarkaskaden von https://github.com/opencv/opencv/blob/master/data/haarcascades/ herunter
|
||||
import cv2
|
||||
import numpy as np
|
||||
|
||||
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
|
||||
eye_cascade = cv2.CascadeClassifier('haarcascade_eye.xml')
|
||||
|
||||
@ -123,31 +123,32 @@ img = cv2.imread('Mensch.jpg')
|
||||
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
|
||||
|
||||
aces = face_cascade.detectMultiScale(gray, 1.3, 5)
|
||||
for (x,y,w,h) in faces:
|
||||
cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)
|
||||
roi_gray = gray[y:y+h, x:x+w]
|
||||
roi_color = img[y:y+h, x:x+w]
|
||||
for x, y, w, h in faces:
|
||||
cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)
|
||||
roi_gray = gray[y : y + h, x : x + w]
|
||||
roi_color = img[y : y + h, x : x + w]
|
||||
eyes = eye_cascade.detectMultiScale(roi_gray)
|
||||
for (ex,ey,ew,eh) in eyes:
|
||||
cv2.rectangle(roi_color,(ex,ey),(ex+ew,ey+eh),(0,255,0),2)
|
||||
for ex, ey, ew, eh in eyes:
|
||||
cv2.rectangle(roi_color, (ex, ey), (ex + ew, ey + eh), (0, 255, 0), 2)
|
||||
|
||||
cv2.imshow('img',img)
|
||||
cv2.imshow('img', img)
|
||||
cv2.waitKey(0)
|
||||
|
||||
cv2.destroyAllWindows()
|
||||
# destroyAllWindows() zerstört alle Fenster
|
||||
# Wenn du ein bestimmtes Fenter zerstören möchtest musst du den genauen Namen des
|
||||
# Wenn du ein bestimmtes Fenster zerstören möchtest, musst du den genauen Namen des
|
||||
# von dir erstellten Fensters übergeben.
|
||||
```
|
||||
|
||||
### Weiterführende Literatur:
|
||||
* Lade Kaskade hier herunter [https://github.com/opencv/opencv/blob/master/data/haarcascades]()
|
||||
* OpenCV Zeichenfunktionen [https://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html]()
|
||||
* Eine aktuelle Sprachenreferenz kann hier gefunden werden [https://opencv.org]()
|
||||
* Zusätzliche Ressourcen können hier gefunden werden [https://en.wikipedia.org/wiki/OpenCV]()
|
||||
|
||||
* Lade Kaskade hier herunter [https://github.com/opencv/opencv/blob/master/data/haarcascades](https://github.com/opencv/opencv/blob/master/data/haarcascades)
|
||||
* OpenCV Zeichenfunktionen [https://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html](https://docs.opencv.org/2.4/modules/core/doc/drawing_functions.html)
|
||||
* Eine aktuelle Sprachenreferenz kann hier gefunden werden [https://opencv.org](https://opencv.org)
|
||||
* Zusätzliche Ressourcen können hier gefunden werden [https://en.wikipedia.org/wiki/OpenCV](https://en.wikipedia.org/wiki/OpenCV)
|
||||
* Gute OpenCV Tutorials
|
||||
* [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_tutorials.html]()
|
||||
* [https://realpython.com/python-opencv-color-spaces]()
|
||||
* [https://pyimagesearch.com]()
|
||||
* [https://www.learnopencv.com]()
|
||||
* [https://docs.opencv.org/master/]()
|
||||
* [https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_tutorials.html](https://opencv-python-tutroals.readthedocs.io/en/latest/py_tutorials/py_tutorials.html)
|
||||
* [https://realpython.com/python-opencv-color-spaces](https://realpython.com/python-opencv-color-spaces)
|
||||
* [https://pyimagesearch.com](https://pyimagesearch.com)
|
||||
* [https://www.learnopencv.com](https://www.learnopencv.com)
|
||||
* [https://docs.opencv.org/master/](https://docs.opencv.org/master/)
|
||||
|
@ -34,7 +34,7 @@ Manche Beispiele sind von <http://learnxinyminutes.com/docs/racket/>.
|
||||
|
||||
;; Funktionsapplikationen werden so geschrieben: (f x y z ...)
|
||||
;; Dabei ist f eine Funktion und x, y, z sind die Operatoren.
|
||||
;; Wenn du eine Literalliste von Daten erstelllen möchtest,
|
||||
;; Wenn du eine Literalliste von Daten erstellen möchtest,
|
||||
;; verwende (quote) um zu verhindern, dass sie ausgewertet zu werden.
|
||||
(quote (+ 1 2)) ; => (+ 1 2)
|
||||
;; Nun einige arithmetische Operationen
|
||||
@ -74,7 +74,7 @@ false ; for Falsch
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; 2. Variablen
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;; Du kannst Variablen setzen indem du (set) verwedest
|
||||
;; Du kannst Variablen setzen indem du (set) verwendest
|
||||
;; eine Variable kann alle Zeichen besitzen außer: ();#"
|
||||
(set some-var 5) ; => 5
|
||||
some-var ; => 5
|
||||
@ -92,7 +92,7 @@ some-var ; => 5
|
||||
|
||||
;;; Listen
|
||||
|
||||
;; Listen sind Vektrorartige Datenstrukturen. (Zufälliger Zugriff ist O(1).
|
||||
;; Listen sind Vektorartige Datenstrukturen. (Zufälliger Zugriff ist O(1).
|
||||
(cons 1 (cons 2 (cons 3 (list)))) ; => (1 2 3)
|
||||
;; 'list' ist ein komfortabler variadischer Konstruktor für Listen
|
||||
(list 1 2 3) ; => (1 2 3)
|
||||
@ -196,5 +196,5 @@ a ; => (3 2)
|
||||
(infix 1 + 2 (infix 3 * 4)) ; => 15
|
||||
|
||||
;; Makros sind nicht hygenisch, Du kannst bestehende Variablen überschreiben!
|
||||
;; Sie sind Codetransformationenen.
|
||||
;; Sie sind Codetransformationen.
|
||||
```
|
||||
|
@ -10,7 +10,7 @@ lang: de-de
|
||||
|
||||
Perl ist eine sehr mächtige, funktionsreiche Programmiersprache mit über 25 Jahren Entwicklungsgeschichte.
|
||||
|
||||
Perl läuft auf über 100 Platformen von portablen Geräten bis hin zu Mainframes. Perl ist geeignet für Rapid-Prototyping und auch groß angelegte Entwicklungs-Projekte.
|
||||
Perl läuft auf über 100 Plattformen von portablen Geräten bis hin zu Mainframes. Perl ist geeignet für Rapid-Prototyping und auch groß angelegte Entwicklungs-Projekte.
|
||||
|
||||
```perl
|
||||
# Einzeilige Kommentare beginnen mit dem # Symbol.
|
||||
@ -30,8 +30,8 @@ Perl läuft auf über 100 Platformen von portablen Geräten bis hin zu Mainframe
|
||||
my $animal = "camel";
|
||||
my $answer = 42;
|
||||
|
||||
# Scalare Werte könnne Zeichenketten, Ganzzahlen und Gleitkomma-Zahlen sein.
|
||||
# Perl convertiert automatisch zwischen diesen Werten wenn nötig.
|
||||
# Scalare Werte können Zeichenketten, Ganzzahlen und Gleitkomma-Zahlen sein.
|
||||
# Perl konvertiert automatisch zwischen diesen Werten wenn nötig.
|
||||
|
||||
## Arrays
|
||||
# Ein Array repräsentiert eine Liste von Werten:
|
||||
@ -42,7 +42,7 @@ my @mixed = ("camel", 42, 1.23);
|
||||
|
||||
|
||||
## Hashes
|
||||
# Ein Hash representiert ein Set von Schlüssel/Wert Paaren:
|
||||
# Ein Hash repräsentiert ein Set von Schlüssel/Wert Paaren:
|
||||
|
||||
my %fruit_color = ("apple", "red", "banana", "yellow");
|
||||
|
||||
@ -55,7 +55,7 @@ my %fruit_color = (
|
||||
# Scalare, Arrays und Hashes sind in perldata sehr genau dokumentiert.
|
||||
# (perldoc perldata)
|
||||
|
||||
# Komplexere Daten-Typen können mit hilfe von Referenzen konstruiert werden.
|
||||
# Komplexere Daten-Typen können mithilfe von Referenzen konstruiert werden.
|
||||
# Dies erlaubt das erstellen von Listen und Hashes in Listen und Hashes.
|
||||
|
||||
#### Bedingte Ausführungs- und Schleifen-Konstrukte.
|
||||
@ -157,7 +157,7 @@ logger("We have a logger subroutine!");
|
||||
|
||||
#### Verwenden von Perl Modulen
|
||||
|
||||
Perl Module liefern eine Menge an Funktionen die dabei Helfen das Rad nicht neu erfinden zu müssen. Perl Module können von CPAN (http://www.cpan.org/) heruntergeladen werden. Einige populäre Module sind in der Perl Distribution selbst bereits enthalten.
|
||||
Perl Module liefern eine Menge an Funktionen die dabei Helfen das Rad nicht neu erfinden zu müssen. Perl Module können von [CPAN](http://www.cpan.org/) heruntergeladen werden. Einige populäre Module sind in der Perl Distribution selbst bereits enthalten.
|
||||
|
||||
Perlfaq enthält Fragen und Antworten zu häufig vorkommenden Aufgaben. Sehr oft sind auch Vorschläge enthalten welches CPAN module am besten geeignet ist.
|
||||
|
||||
|
@ -34,7 +34,7 @@ offiziellen IDE, damit die Programme kompiliert und ausgeführt werden können.
|
||||
/*
|
||||
Da Processing von Java abstammt, ist die Syntax für Kommentare gleich
|
||||
wie bei Java (wie du vielleicht oben bemerkt hast)!
|
||||
Mehrzeilige Kommentare werden wie hier umschloßen.
|
||||
Mehrzeilige Kommentare werden wie hier umschlossen.
|
||||
*/
|
||||
|
||||
/* -------------------------------------------------
|
||||
@ -59,7 +59,7 @@ size(width, height, [renderer]); // bestimme die Canvasgröße mit dem optionale
|
||||
// Parameter `renderer`.
|
||||
// Du wirst innerhalb dieses Dokuments noch weitere Parameter sehen.
|
||||
|
||||
// Wenn du möchstest, dass Code unendlich oft ausgeführt wird, so muss dieser
|
||||
// Wenn du möchtest, dass der Code unendlich oft ausgeführt wird, so muss dieser
|
||||
// Code innerhalb der `draw()`-Methode stehen.
|
||||
// `draw()` muss existieren, wenn du möchtest, dass das Programm durchgehend
|
||||
// läuft. Die `draw()`-Methode darf nur einmal vorkommen.
|
||||
@ -107,7 +107,7 @@ double doubleValue = 1.12345D // Double (64-Bit Gleitkommazahl)
|
||||
// lediglich die wichtigsten durch.
|
||||
|
||||
// String
|
||||
// Während der Datentyp `char` einfache Anzührungszeichen (' ') braucht, haben
|
||||
// Während der Datentyp `char` einfache Anführungszeichen (' ') braucht, haben
|
||||
// Strings doppelte Anführungszeichen (" ").
|
||||
String sampleString = "Hallo, Processing!";
|
||||
// Strings können auch durch ein Array von `char`s erstellt werden.
|
||||
@ -137,11 +137,11 @@ ArrayList<Integer> intArrayList = new ArrayList<Integer>();
|
||||
// Da Processing auf Java basiert, unterstützt Processing die Objektorientierte
|
||||
// Programmierung. Dies bedeutet, dass du grundsätzlich jegliche Datentypen
|
||||
// selber erstellen kannst und diese nach deinen Bedürfnissen manipulieren kannst.
|
||||
// Selbstverständlich muss eine Klasse definiert werden bevor du ein Objekt
|
||||
// davon instanzieren kannst.
|
||||
// Selbstverständlich muss eine Klasse definiert werden, bevor du ein Objekt
|
||||
// davon instanziieren kannst.
|
||||
// Format: ClassName InstanceName
|
||||
SomeRandomClass myObject // hier musst du das Objekt später instazieren
|
||||
// Hier wird das Objekt direkt instanziert:
|
||||
SomeRandomClass myObject // hier musst du das Objekt später instanziieren
|
||||
// Hier wird das Objekt direkt instanziiert:
|
||||
SomeRandomClass myObjectInstantiated = new SomeRandomClass();
|
||||
|
||||
// Processing hat noch weitere Collections (wie zum Beispiel Dictionaries und
|
||||
@ -255,7 +255,6 @@ Da du nun die Grundsätze der Programmiersprache verstanden hast, schauen wir
|
||||
uns nun das Beste an Processing an - Das Zeichnen!
|
||||
|
||||
```
|
||||
|
||||
/* -------------------------------------------------
|
||||
Figuren
|
||||
-------------------------------------------------
|
||||
@ -349,7 +348,7 @@ sphere(radius); // Die Größe wird definiert durch den Parameter `radius`
|
||||
-------------------------------------------------
|
||||
*/
|
||||
|
||||
// Tranformationen sind nützlich, um ständig zu wissen, wo die Koordinaten und
|
||||
// Transformationen sind nützlich, um ständig zu wissen, wo die Koordinaten und
|
||||
// die Ecken einer Form sind, welche du gezeichnet hast. Grundsätzlich sind dies
|
||||
// Matrizenoperationen. `pushMatrix()`, `popMatrix()` und `translate()`.
|
||||
pushMatrix(); // Speichert das aktuelle Koordinatensystem auf dem Stack
|
||||
@ -363,7 +362,7 @@ translate(x,y); // Setzt den Ursprung zu diesem Punkt.
|
||||
translate(x, y, z); // Pendant zu der oberen Funktion im dreidimensionalen Raum
|
||||
|
||||
// Rotationen
|
||||
rotate(angle); // Rotiere, um den Betrag, welcher spezifiert wurde.
|
||||
rotate(angle); // Rotiere, um den Betrag, welcher spezifiziert wurde.
|
||||
// Es gibt drei Pendants im dreidimensionalen Raum.
|
||||
// Namentlich sind dies: `rotateX(angle)`, `rotateY(angle)` und `rotateZ(angle)`
|
||||
|
||||
@ -406,7 +405,7 @@ Wenn du weitere Dinge mit Processing kennenlernen willst, dann gibt es unzählig
|
||||
Dinge, welche du mit Processing machen kannst. Das Rendern von Modellen,
|
||||
Schattierungen und viele mehr. Für ein kurzes Tutorial bietet Processing zu viel,
|
||||
daher verweise ich dich, falls du interessiert bist, auf die offizielle
|
||||
Dokumentaion.
|
||||
Dokumentation.
|
||||
|
||||
```
|
||||
// Bevor wir weiterfahren, werde ich einige Aspekte zum Importieren von
|
||||
@ -432,7 +431,7 @@ was man in Processing mit nur wenigen Zeilen Code machen kann.
|
||||
Kopiere den nachfolgenden Code in deine Processing IDE.
|
||||
|
||||
```
|
||||
// Disclaimer: Ich habe das Porgramm nicht selbst geschriben. Diese Skizze
|
||||
// Disclaimer: Ich habe das Programm nicht selbst geschrieben. Diese Skizze
|
||||
// stammt aus openprocessing, allerdings soll dieses Programm zeigen, wie wenig
|
||||
// Zeilen Code notwendig sind, um etwas Cooles zu machen.
|
||||
// Abgerufen von: (https://www.openprocessing.org/sketch/559769)
|
||||
@ -483,7 +482,7 @@ void branch(float len) {
|
||||
}
|
||||
```
|
||||
|
||||
Processing ist einfach zu erlernen und ist vorallem nützlich, um Multimedia-
|
||||
Processing ist einfach zu erlernen und ist vor allem nützlich, um Multimedia-
|
||||
Inhalte (auch in 3D) zu erstellen ohne viel Code zu schreiben. Es ist so einfach
|
||||
gehalten, dass man den Code durchlesen kann und man versteht den Programmablauf
|
||||
bereits.
|
||||
|
@ -8,16 +8,12 @@ translators:
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
## Erste Schritte mit Pug
|
||||
|
||||
Pug ist eine kleine Sprache, die zu HTML kompiliert. Sie hat eine
|
||||
saubere Syntax mit zusätzlichen Funktionen wie if Anweisungen und Schleifen.
|
||||
Sie kann auch als serverseitige Templatingsprache für Serversprachen
|
||||
wie NodeJS verwendet werden.
|
||||
|
||||
### Die Sprache
|
||||
```pug
|
||||
|
||||
//- Einzeilenkommentar
|
||||
|
||||
//- Mehrzeiliger
|
||||
@ -88,10 +84,10 @@ div(class=meineKlasse)
|
||||
|
||||
//- JS Stil
|
||||
- const meineStile = {'color':'white', 'background-color':'blue'}
|
||||
div(styles=meineStile)
|
||||
//- <div styles="{"color":"white","background-color":"blue"}"></div>
|
||||
div(style=meineStile)
|
||||
//- <div style="color:white;background-color:blue;"></div>
|
||||
|
||||
//- JS Attributte
|
||||
//- JS Attribute
|
||||
- const meineAttribute = {"src": "foto.png", "alt": "meine Bilder"}
|
||||
img&attributes(meineAttribute)
|
||||
//- <img src="foto.png" alt="meine Bilder">
|
||||
@ -162,13 +158,13 @@ case bestellungsStatus
|
||||
//- <p class="warn">Deine Bestellung steht noch aus</p>
|
||||
|
||||
//- --INCLUDE--
|
||||
//- File path -> "includes/nav.png"
|
||||
//- File path -> "includes/nav.pug"
|
||||
h1 Firmenname
|
||||
nav
|
||||
a(href="index.html") Home
|
||||
a(href="about.html") Über uns
|
||||
|
||||
//- Dateipfad -> "index.png"
|
||||
//- Dateipfad -> "index.pug"
|
||||
html
|
||||
body
|
||||
include includes/nav.pug
|
||||
@ -198,11 +194,10 @@ mixin comment(name, kommentar)
|
||||
div.comment-text= kommentar
|
||||
+comment("Bob", "Das ist super")
|
||||
//- <div>Hallo</div>
|
||||
|
||||
```
|
||||
|
||||
|
||||
### Zusätzliche Ressourcen
|
||||
|
||||
- [The Site](https://pugjs.org/)
|
||||
- [The Docs](https://pugjs.org/api/getting-started.html)
|
||||
- [Github Repo](https://github.com/pugjs/pug)
|
||||
- [GitHub Repo](https://github.com/pugjs/pug)
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
category: tool
|
||||
tool: PyQT
|
||||
category: framework
|
||||
framework: PyQT
|
||||
filename: learnpyqt-de.py
|
||||
contributors:
|
||||
- ["Nathan Hughes", "https://github.com/sirsharpest"]
|
||||
@ -9,19 +9,19 @@ translators:
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
**Qt** ist eine weit bekanntes Framework mit den man plattformunabhängige Programme schreiben kann,
|
||||
die auf verschiedenen Sotfware und Hardware Plattformen laufen mit kleinen oder keinen Änderungen im Code.
|
||||
Dabei besitzen sie trozdem die Power und Geschwindigkeit von nativen Anwendungen.
|
||||
**Qt** ist ein weit bekanntes Framework, mit dem man plattformunabhängige Programme schreiben kann,
|
||||
die auf verschiedenen Software- und Hardwareplattformen laufen, mit kleinen oder keinen Änderungen im Code.
|
||||
Dabei besitzen sie trotzdem die Power und Geschwindigkeit von nativen Anwendungen.
|
||||
**Qt** wurde ursprünglich in *C++** geschrieben.
|
||||
|
||||
Das ist eine Adaption von dem C++ Intro für QT von [Aleksey Kholovchuk](https://github.com/vortexxx192),
|
||||
manche der Codebeispiele sollte in der selben Funktionalität resultieren.
|
||||
manche der Codebeispiele sollten in derselben Funktionalität resultieren.
|
||||
Diese Version wurde in pyqt erstellt.
|
||||
|
||||
```python
|
||||
import sys
|
||||
from PyQt4 import QtGui
|
||||
|
||||
|
||||
def window():
|
||||
# Erschafft ein Anwendungsobjekt.
|
||||
app = QtGui.QApplication(sys.argv)
|
||||
@ -31,7 +31,7 @@ def window():
|
||||
b = QtGui.QLabel(w)
|
||||
# Setzt einen Text für das Label.
|
||||
b.setText("Hello World!")
|
||||
# Setzt die Größe und die Platzierungsinfomationen.
|
||||
# Setzt die Größe und die Platzierungsinformationen.
|
||||
w.setGeometry(100, 100, 200, 50)
|
||||
b.move(50, 20)
|
||||
# Setzt unserem Fenster einen schönen Titel.
|
||||
@ -43,15 +43,14 @@ def window():
|
||||
|
||||
if __name__ == '__main__':
|
||||
window()
|
||||
|
||||
```
|
||||
|
||||
Damit wir weitere fortgeschrittene Funktionen in **pyqt** verwenden können,
|
||||
müssen wir anfangen zusätzliche Elemente zu bauen.
|
||||
Hier zeigen wir wie man eine Dialog Popup Box einführt.
|
||||
Diese ist nützlich, um den Benutzer eine Entscheidung zu bestätigen oder um Informationen anzuzeigen.
|
||||
Hier zeigen wir wie man eine Dialog Popup Box einführt.
|
||||
Diese ist nützlich, um dem Benutzer eine Entscheidung zu bestätigen oder Informationen anzuzeigen.
|
||||
|
||||
```Python
|
||||
```python
|
||||
import sys
|
||||
from PyQt4.QtGui import *
|
||||
from PyQt4.QtCore import *
|
||||
@ -70,9 +69,9 @@ def window():
|
||||
w.setWindowTitle("PyQt Dialog")
|
||||
w.show()
|
||||
sys.exit(app.exec_())
|
||||
|
||||
|
||||
# Diese Funktion soll ein Dialogfenster mit einem Knopf erschaffen.
|
||||
# Der Knopf wartet bis er geklickt wird und beendet das Programm
|
||||
# Der Knopf wartet, bis er geklickt wird, und beendet das Programm.
|
||||
def showdialog():
|
||||
d = QDialog()
|
||||
b1 = QPushButton("ok", d)
|
||||
@ -80,7 +79,7 @@ def showdialog():
|
||||
d.setWindowTitle("Dialog")
|
||||
# Diese Modalität sagt dem Popup, dass es den Parent blocken soll, solange es aktiv ist.
|
||||
d.setWindowModality(Qt.ApplicationModal)
|
||||
# Beim klicken möchte ich, dass der gesamte Prozess beendet wird.
|
||||
# Beim Klicken möchte ich, dass der gesamte Prozess beendet wird.
|
||||
b1.clicked.connect(sys.exit)
|
||||
d.exec_()
|
||||
|
||||
|
@ -12,13 +12,10 @@ lang: de-de
|
||||
Anmerkungen des ursprünglichen Autors:
|
||||
Python wurde in den frühen Neunzigern von Guido van Rossum entworfen. Es ist heute eine der beliebtesten Sprachen. Ich habe mich in Python wegen seiner syntaktischen Übersichtlichkeit verliebt. Eigentlich ist es ausführbarer Pseudocode.
|
||||
|
||||
Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service].
|
||||
|
||||
Hinweis: Dieser Beitrag bezieht sich implizit auf Python 3. Falls du lieber Python 2.7 lernen möchtest, schau [hier](http://learnxinyminutes.com/docs/pythonlegacy/) weiter. Beachte hierbei,
|
||||
dass Python 2 als veraltet gilt und für neue Projekte nicht mehr verwendet werden sollte.
|
||||
|
||||
```python
|
||||
|
||||
# Einzeilige Kommentare beginnen mit einer Raute (Doppelkreuz)
|
||||
|
||||
""" Mehrzeilige Strings werden mit
|
||||
@ -104,7 +101,7 @@ False or True #=> True
|
||||
# Strings können auch addiert werden! Vermeide dies aber lieber.
|
||||
"Hallo " + "Welt!" #=> "Hallo Welt!"
|
||||
# Strings können ohne "+" addiert werden
|
||||
"Hallo " "welt!" # => "Hallo Welt!"
|
||||
"Hallo " "Welt!" # => "Hallo Welt!"
|
||||
|
||||
# Ein String kann wie eine Liste von Zeichen verwendet werden
|
||||
"Das ist ein String"[0] #=> 'D'
|
||||
@ -113,13 +110,13 @@ False or True #=> True
|
||||
"{} können {} werden".format("Strings", "formatiert")
|
||||
|
||||
# Schneller geht das mit Wiederholungen
|
||||
"{0} mag Spagetthi, {0} liebt es zu Schwimmen und ganz besonders mag {0} {1}".format("Hans", "Blattsalat")
|
||||
#=> "Hans mag Spagetthi, Hans liebt es zu Schwimmen und ganz besonders mag Hans Blattsalat"
|
||||
"{0} mag Spaghetti, {0} liebt es zu Schwimmen und ganz besonders mag {0} {1}".format("Hans", "Blattsalat")
|
||||
#=> "Hans mag Spaghetti, Hans liebt es zu Schwimmen und ganz besonders mag Hans Blattsalat"
|
||||
|
||||
# Die Formatierung kann auch mit `f-strings` oder formattierten Strings gemacht
|
||||
# Die Formatierung kann auch mit `f-strings` oder formatierten Strings gemacht
|
||||
# werden (ab Python 3.6+)
|
||||
name = "Sandra"
|
||||
f"Sie hat gesagt, ihr name sei {name}." # => Sie hat gesagt, ihr Name sei Sandra."
|
||||
f"Sie hat gesagt, ihr Name sei {name}." # => Sie hat gesagt, ihr Name sei Sandra."
|
||||
# Es ist möglich, andere Anweisungen innerhalb der geschweiften Klammern zu
|
||||
# setzen, welche dann im Output des Strings angezeigt werden.
|
||||
f"{name} ist {len(name)} Zeichen lang" # => Sandra ist 6 Zeichen lang.
|
||||
@ -224,7 +221,7 @@ d, e, f = 4, 5, 6
|
||||
# Es ist kinderleicht, zwei Werte zu tauschen
|
||||
e, d = d, e # d ist nun 5 und e ist nun 4
|
||||
|
||||
# Dictionarys (Wörterbucher) speichern Schlüssel-Werte-Paare
|
||||
# Dictionarys (Wörterbücher) speichern Schlüssel-Werte-Paare
|
||||
empty_dict = {}
|
||||
# Hier ein gefülltes Wörterbuch
|
||||
filled_dict = {"one": 1, "two": 2, "three": 3}
|
||||
@ -245,7 +242,7 @@ list(filled_dict.values()) #=> [3, 2, 1]
|
||||
"one" in filled_dict #=> True
|
||||
1 in filled_dict #=> False
|
||||
|
||||
# Einen nicht vorhandenenen Schlüssel zu suchen, löst einen KeyError aus
|
||||
# Einen nicht vorhandenen Schlüssel zu suchen, löst einen KeyError aus
|
||||
filled_dict["four"] # KeyError
|
||||
|
||||
# Mit der get-Methode verhindern wir das
|
||||
@ -264,7 +261,7 @@ filled_dict.update({"four":4}) #=> {"one": 1, "two": 2, "three": 3, "four": 4}
|
||||
#filled_dict["four"] = 4 # noch ein Weg, Werte hinzuzufügen
|
||||
|
||||
# Schlüssel von einem Wörterbuch entfernen
|
||||
del filled_dict["one"] # Entfert den Schlüssel "one"
|
||||
del filled_dict["one"] # Entfernt den Schlüssel "one"
|
||||
|
||||
# Sets speichern Mengen
|
||||
empty_set = set()
|
||||
@ -623,7 +620,6 @@ def say(say_please=False):
|
||||
|
||||
print(say()) # Can you buy me a beer?
|
||||
print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
|
||||
|
||||
```
|
||||
|
||||
## Lust auf mehr?
|
||||
@ -635,8 +631,7 @@ print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
|
||||
* [Dive Into Python](http://www.diveintopython.net/)
|
||||
* [Ideas for Python Projects](http://pythonpracticeprojects.com)
|
||||
* [The Official Docs](http://docs.python.org/3/)
|
||||
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/en/latest/)
|
||||
* [A Crash Course in Python for Scientists](http://nbviewer.ipython.org/5920182)
|
||||
* [Hitchhiker's Guide to Python](http://docs.python-guide.org/)
|
||||
* [Python Course](http://www.python-course.eu/index.php)
|
||||
* [First Steps With Python](https://realpython.com/learn/python-first-steps/)
|
||||
|
||||
|
@ -11,8 +11,6 @@ lang: de-de
|
||||
Anmerkungen des ursprünglichen Autors:
|
||||
Python wurde in den frühen Neunzigern von Guido van Rossum entworfen. Es ist heute eine der beliebtesten Sprachen. Ich habe mich in Python wegen seiner syntaktischen Übersichtlichkeit verliebt. Eigentlich ist es ausführbarer Pseudocode.
|
||||
|
||||
Feedback ist herzlich willkommen! Ihr erreicht mich unter [@louiedinh](http://twitter.com/louiedinh) oder louiedinh [at] [google's email service]
|
||||
|
||||
Hinweis: Dieser Beitrag bezieht sich besonders auf Python 2.7, er sollte aber auf Python 2.x anwendbar sein. Haltet Ausschau nach einem Rundgang durch Python 3, der bald erscheinen soll.
|
||||
|
||||
```python
|
||||
@ -194,7 +192,7 @@ d, e, f = 4, 5, 6
|
||||
e, d = d, e # d is now 5 and e is now 4
|
||||
|
||||
|
||||
# Dictionarys (Wörterbucher) speichern Key-Value-Paare
|
||||
# Dictionarys (Wörterbücher) speichern Key-Value-Paare
|
||||
empty_dict = {}
|
||||
# Hier ein gefülltes Wörterbuch
|
||||
filled_dict = {"one": 1, "two": 2, "three": 3}
|
||||
@ -215,7 +213,7 @@ filled_dict.values() #=> [3, 2, 1]
|
||||
"one" in filled_dict #=> True
|
||||
1 in filled_dict #=> False
|
||||
|
||||
# Einen nicht vorhandenenen Schlüssel zu suchen, löst einen KeyError aus
|
||||
# Einen nicht vorhandenen Schlüssel zu suchen, löst einen KeyError aus
|
||||
filled_dict["four"] # KeyError
|
||||
|
||||
# Mit der get-Methode verhindern wir das
|
||||
@ -745,7 +743,6 @@ def say(say_please=False):
|
||||
|
||||
print(say()) # Can you buy me a beer?
|
||||
print(say(say_please=True)) # Can you buy me a beer? Please! I am poor :(
|
||||
|
||||
```
|
||||
|
||||
## Lust auf mehr?
|
||||
|
@ -1,6 +1,6 @@
|
||||
---
|
||||
category: tool
|
||||
tool: Qt Framework
|
||||
category: framework
|
||||
framework: Qt Framework
|
||||
language: C++
|
||||
filename: learnqt-de.cpp
|
||||
contributors:
|
||||
@ -10,9 +10,9 @@ translators:
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
**Qt** ist ein weithin bekanntes Framework zum Entwickeln von cross-platform Software,
|
||||
die auf verschiedenen Hard- und Softwareplatformen mit wenig oder keinen Veränderungen im Code läuft.
|
||||
Dabei besitzt man die Power und Geschiwindigkeit von nativen Anwendungen.
|
||||
**Qt** ist ein weithin bekanntes Framework zum Entwickeln von Cross-Platform Software,
|
||||
die auf verschiedenen Hard- und Softwareplattformen mit wenig oder keinen Veränderungen im Code läuft.
|
||||
Dabei besitzt man die Power und Geschwindigkeit von nativen Anwendungen.
|
||||
Obwohl **Qt** ursprünglich in *C++* geschrieben wurde,
|
||||
gibt es verschiedene Ports für andere Sprachen: *[PyQt](https://learnxinyminutes.com/docs/pyqt/)*, *QtRuby*, *PHP-Qt*, etc.
|
||||
|
||||
@ -29,7 +29,7 @@ Dieses Tutorial zeigt, wie man das in *C++* macht.
|
||||
#include <QLineEdit>
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
// Erstellt ein Objekt um applikationsweit die Resourcen zu managen.
|
||||
// Erstellt ein Objekt um applikationsweit die Ressourcen zu managen.
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// Erstellt ein Line edit Widget und zeigt es auf dem Bildschirm
|
||||
@ -41,7 +41,7 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
```
|
||||
|
||||
Die GUI bezogene Teile von **Qt** bestehen aus *Widgets* und den *Verbindungen*
|
||||
Die GUI-bezogene Teile von **Qt** bestehen aus *Widgets* und den *Verbindungen*
|
||||
dazwischen.
|
||||
|
||||
[Lies mehr über Widgets](http://doc.qt.io/qt-5/qtwidgets-index.html)
|
||||
@ -66,7 +66,7 @@ int main(int argc, char *argv[]) {
|
||||
QDialog dialogWindow;
|
||||
dialogWindow.show();
|
||||
|
||||
// Füge ein vertikales Layout hinzu
|
||||
// Füge ein vertikales Layout hinzu.
|
||||
QVBoxLayout layout;
|
||||
dialogWindow.setLayout(&layout);
|
||||
|
||||
@ -101,7 +101,7 @@ Als Nächstes lernen wir, dass wir nicht nur Standard Widgets verwenden können,
|
||||
sondern auch ihr Verhalten mithilfe von Vererbung verändern können.
|
||||
Lass uns einen Button erschaffen, der zählt, wie häufig er gedrückt wird.
|
||||
Dafür definieren wir unsere eigene Klasse *CounterLabel*.
|
||||
Diese muss wegen der speziellen Qt Architektur in einer seperaten Datei deklariert werden.
|
||||
Diese muss wegen der speziellen Qt Architektur in einer separaten Datei deklariert werden.
|
||||
|
||||
```c++
|
||||
// counterlabel.hpp
|
||||
@ -164,10 +164,10 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
```
|
||||
|
||||
Das wars! Natürlich ist das Qt Framework erheblich größer, als der der Teil der in diesem Tutorial behandelt wurde.
|
||||
Das wars! Natürlich ist das Qt Framework erheblich größer als der Teil, der in diesem Tutorial behandelt wurde.
|
||||
Das heißt, es gibt viel zu lesen und zu üben.
|
||||
|
||||
## Further reading
|
||||
## Weitere Informationen
|
||||
|
||||
- [Qt 4.8 tutorials](http://doc.qt.io/qt-4.8/tutorials.html)
|
||||
- [Qt 5 tutorials](http://doc.qt.io/qt-5/qtexamplesandtutorials.html)
|
||||
|
@ -10,39 +10,36 @@ lang: de-de
|
||||
---
|
||||
|
||||
RST ist ein Dateiformat, das von der Python Community entwickelt wurde,
|
||||
|
||||
um Dokumentation zu schreiben (und ist somit Teil von Docutils).
|
||||
|
||||
RST-Dateien sind simple Textdateien mit einer leichtgewichtigen Syntax (im Vergleich zu HTML).
|
||||
|
||||
um Dokumentation zu schreiben (und ist somit Teil von Docutils).
|
||||
RST-Dateien sind simple Textdateien mit einer leichtgewichtigen Syntax (im
|
||||
Vergleich zu HTML).
|
||||
|
||||
## Installation
|
||||
|
||||
Um Restructured Text zu vewenden musst du [Python](http://www.python.org)
|
||||
|
||||
installieren und das `docutils` Packet installieren. `docutils` kann mit dem folgenden
|
||||
|
||||
Befehl auf der Kommandozeile installiert werden:
|
||||
Um Restructured Text zu verwenden, musst du [Python](http://www.python.org)
|
||||
installieren und das `docutils` Paket installieren. `docutils` kann mit dem
|
||||
folgenden Befehl auf der Kommandozeile installiert werden:
|
||||
|
||||
```bash
|
||||
$ easy_install docutils
|
||||
easy_install docutils
|
||||
```
|
||||
|
||||
Wenn auf deinem System `pip` installiert kannst du es statdessen auch verwenden:
|
||||
Ebenso kann die Installation mit `pip`
|
||||
|
||||
```bash
|
||||
$ pip install docutils
|
||||
pip install docutils
|
||||
```
|
||||
|
||||
initiiert werden.
|
||||
|
||||
## Dateisyntax
|
||||
|
||||
Ein einfaches Beispiel für die Dateisyntax:
|
||||
|
||||
```
|
||||
.. Zeilen, die mit zwei Punkten starten sind spezielle Befehle.
|
||||
.. Zeilen, die mit zwei Punkten starten sind spezielle Befehle.
|
||||
|
||||
.. Wenn kein Befehl gefunden wird, wird die Zeile als Kommentar gewertet.
|
||||
.. Wenn kein Befehl gefunden wird, wird die Zeile als Kommentar gewertet.
|
||||
|
||||
============================================================================
|
||||
Haupttitel werden mit Gleichheitszeichen darüber und darunter gekennzeichnet
|
||||
@ -57,7 +54,7 @@ Titel werden auch mit Gleichheitszeichen unterstrichen
|
||||
Untertitel werden mit Strichen gekennzeichnet
|
||||
---------------------------------------------
|
||||
|
||||
Text in *kursiv* oder in **fett**. Du kannst Text als Code "makieren", wenn
|
||||
Text in *kursiv* oder in **fett**. Du kannst Text als Code "markieren", wenn
|
||||
du doppelte Backquotes verwendest ``: ``print()``.
|
||||
|
||||
Listen sind so einfach wie in Markdown:
|
||||
@ -75,43 +72,47 @@ oder
|
||||
Tabellen sind einfach zu schreiben:
|
||||
|
||||
=========== ==========
|
||||
Land Hauptstadt
|
||||
Land Hauptstadt
|
||||
=========== ==========
|
||||
Frankreich Paris
|
||||
Japan Tokyo
|
||||
=========== ========
|
||||
|
||||
Komplexere Tabellen (zusammengeführte Spalten und Zeilen) können einfach
|
||||
erstellt werden, aber ich empfehle dir dafür die komplette Dokumentation zu lesen :)
|
||||
Komplexere Tabellen (zusammengeführte Spalten und Zeilen) können einfach
|
||||
erstellt werden, aber ich empfehle dir dafür die komplette Dokumentation zu
|
||||
lesen :)
|
||||
|
||||
Es gibt mehrere Möglichkeiten um Links zu machen:
|
||||
|
||||
- Wenn man einen Unterstrich hinter einem Wort hinzufügt: Github_ Zusätzlich
|
||||
muss man die Zielurl nach dem Text hinzufügen.
|
||||
- Wenn man einen Unterstrich hinter einem Wort hinzufügt: GitHub_ Zusätzlich
|
||||
muss man die Zielurl nach dem Text hinzufügen.
|
||||
(Dies hat den Vorteil, dass man keine unnötigen Urls in lesbaren Text einfügt.
|
||||
- Wenn man die vollständige Url eingibt : https://github.com/
|
||||
- Wenn man die vollständige Url eingibt: https://github.com/
|
||||
(Dies wird automatisch in ein Link konvertiert.)
|
||||
- Wenn man es mehr Markdown ähnlich eingibt: `Github <https://github.com/>`_ .
|
||||
|
||||
.. _Github https://github.com/
|
||||
- Wenn man es mehr Markdown ähnlich eingibt: `GitHub <https://github.com/>`_ .
|
||||
|
||||
.. _GitHub https://github.com/
|
||||
```
|
||||
|
||||
|
||||
## Wie man es verwendet
|
||||
|
||||
RST kommt mit docutils, dort hast du den Befehl `rst2html`, zum Beispiel:
|
||||
Mit der Installation von [docutils](https://docutils.sourceforge.io/) bietet
|
||||
sich beispielsweise die Umwandlung zu html (mehrere Standards stehen zur
|
||||
Auswahl) an:
|
||||
|
||||
```bash
|
||||
$ rst2html myfile.rst output.html
|
||||
rst2html myfile.rst output.html
|
||||
```
|
||||
|
||||
*Anmerkung : Auf manchen Systemen könnte es rst2html.py sein*
|
||||
*Anmerkung: Auf manchen Systemen könnte es `rst2html.py` sein.*
|
||||
|
||||
Es gibt komplexere Anwendungen, die das RST Format verwenden:
|
||||
Weitere Exporte bieten beispielsweise `rst2latex`, `rst2man`, `rst2odt`,
|
||||
`rst2pdf` und `rst2xml`.
|
||||
|
||||
- [Pelican](http://blog.getpelican.com/), ein statischer Websitengenerator
|
||||
- [Sphinx](http://sphinx-doc.org/), Ein Dokumentationsgenerator
|
||||
Es gibt komplexere Anwendungen, die das RST Format verwenden:
|
||||
|
||||
- [Pelican](http://blog.getpelican.com/), ein statischer Webseitengenerator
|
||||
- [Sphinx](http://sphinx-doc.org/), ein Dokumentationsgenerator
|
||||
- und viele Andere
|
||||
|
||||
## Zum Lesen
|
||||
|
@ -75,7 +75,7 @@ nil.class #=> NilClass
|
||||
true.class #=> TrueClass
|
||||
false.class #=> FalseClass
|
||||
|
||||
# Gleicheit
|
||||
# Gleichheit
|
||||
1 == 1 #=> true
|
||||
2 == 1 #=> false
|
||||
|
||||
@ -190,7 +190,7 @@ array = [1, 2, 3, 4, 5] #=> [1, 2, 3, 4, 5]
|
||||
# Array können verschiedene Typen beinhalten
|
||||
[1, 'hello', false] #=> [1, "hello", false]
|
||||
|
||||
## Arrays könnenindiziert werden.
|
||||
## Arrays können indiziert werden.
|
||||
|
||||
# Von vorne...
|
||||
array[0] #=> 1
|
||||
@ -207,8 +207,8 @@ array[2, 3] #=> [3, 4, 5]
|
||||
# ...oder mit einem Range...
|
||||
array[1..3] #=> [2, 3, 4]
|
||||
|
||||
# Du kanns ein Array umkehren.
|
||||
# Gib ein neues Array mit umgkehrten Werten zurück
|
||||
# Du kannst ein Array umkehren.
|
||||
# Gib ein neues Array mit umgekehrten Werten zurück
|
||||
[1,2,3].reverse #=> [3,2,1]
|
||||
|
||||
# Kehre ein Array an Ort und Stelle um, um die Variable mit den
|
||||
@ -257,7 +257,7 @@ hash.value?(3) #=> true
|
||||
# Tipp: Arrays und Hashes sind Enumerables!
|
||||
# Sie haben viele nützliche Methoden gemein, wie each, map, count, und andere.
|
||||
|
||||
# Kontrolstrukturen
|
||||
# Kontrollstrukturen
|
||||
|
||||
# Bedingungen
|
||||
if true
|
||||
@ -427,7 +427,7 @@ surround { puts 'hallo Welt' }
|
||||
|
||||
# Blocks können in ein 'Proc' Objekt umgewandelt werden.
|
||||
# Dieses ist eine Art Container um den Block und erlaubt ihn an eine
|
||||
# andere Methode zu übergeben, ihn in einen anderen Gültigkeitsbereicht
|
||||
# andere Methode zu übergeben, ihn in einen anderen Gültigkeitsbereich
|
||||
# einzubinden oder ihn andersweitig zu verändern.
|
||||
# Am häufigsten findet man dies bei Parameterlisten von Methoden, in Form
|
||||
# eines letzten '&block' Parameters, der den Block – wenn es einen gibt –
|
||||
@ -487,7 +487,7 @@ best *ranked_competitors
|
||||
# Wenn ein Methodenname mit einem Ausrufezeichen endet, dann tut diese Methode
|
||||
# per Konvention etwas Destruktives, wie z.B. das aufrufende Objekt zu
|
||||
# verändern.
|
||||
# Viele Mehtoden haben eine !-Version um eine direkte Änderung zu machen und
|
||||
# Viele Methoden haben eine !-Version um eine direkte Änderung zu machen und
|
||||
# eine Nicht-!-Version, die ein neues Objekt mit den Veränderungen zurück gibt.
|
||||
company_name = "Dunder Mifflin"
|
||||
company_name.upcase #=> "DUNDER MIFFLIN"
|
||||
|
@ -72,7 +72,7 @@ Am ausgereiftesten und stabilsten:
|
||||
|
||||
* [MRI](https://github.com/ruby/ruby) - Geschrieben in C, das ist die Referenz Implementierung.
|
||||
Sie ist 100% kompatibel (mit sich selbst ;-). Alle anderen rubies
|
||||
bleiben kompatibel mit MRI (siehe [RubySpec](#rubyspec) weiter unten).
|
||||
bleiben kompatibel mit MRI (siehe [Ruby Spec](#ruby-spec) weiter unten).
|
||||
* [JRuby](http://jruby.org/) - Geschrieben in Java and Ruby, Robust und ziemlich schnell.
|
||||
Der größte Vorteil von JRuby ist die Interoperabilität mit JVM/Java und damit die
|
||||
Benutzung von Ruby im Java Ecosystem.
|
||||
@ -91,16 +91,16 @@ Weniger ausgereift/kompatibel:
|
||||
* [Topaz](http://topazruby.com/) - Geschrieben in RPython (via PyPy)
|
||||
Topaz ist noch ziemlich jung und versucht die schnellste Implementierung
|
||||
zu werden.
|
||||
* [IronRuby](http://ironruby.net/) - Geschrieben in C# für die .NET Plaftform
|
||||
* [IronRuby](http://ironruby.net/) - Geschrieben in C# für die .NET Plattform
|
||||
Das letzte Release von IronRuby ist mittlerweile 5 Jahre her.
|
||||
|
||||
Die Ruby Implementierungen haben ihre eigenen Versionsnummern, sind aber
|
||||
trotzdem immer zu einer MRI Version kompatibel.
|
||||
Viele können sogar zwischen verschiedenen Modi wechseln (1.8 mode -> 1.9 mode)
|
||||
|
||||
## RubySpec
|
||||
## Ruby Spec
|
||||
|
||||
Die meisten Ruby Implementierungen vertrauen der [RubySpec](http://rubyspec.org/).
|
||||
Die meisten Ruby Implementierungen vertrauen der [Ruby Spec](https://github.com/ruby/spec).
|
||||
sehr stark. Da Ruby keine offizielle Spezifikation hat, hat die
|
||||
Community ausführbare Specs (in Ruby) geschrieben, um so die Kompatibilität
|
||||
zur MRI testen zu können.
|
||||
|
@ -11,7 +11,7 @@ filename: lernerust-de.rs
|
||||
Rust ist eine Programmiersprache von Mozilla Research.
|
||||
Rust vereint Sicherheit, Nebenläufigkeit und eine hohe Praxistauglichkeit.
|
||||
|
||||
Sicherheit bedeuted, dass Programmierfehler ausgeschlossen werden, die zu
|
||||
Sicherheit bedeutet, dass Programmierfehler ausgeschlossen werden, die zu
|
||||
Speicherzugriffsfehlern führen könnten. Das funktioniert u.a. dadurch, dass
|
||||
es keinen Garbage Collector gibt, sondern ein besonderes Typsystem.
|
||||
|
||||
@ -21,8 +21,8 @@ entwickelt, dass es einfach keine stabile gab und geraten wurde den
|
||||
nightly build zu nutzen.
|
||||
|
||||
Am 15. Mai 2015 wurde Rust 1.0 freigegeben, und zwar mit der Garantie einer
|
||||
Abwärtskompatabilität. Verbesserungen der Kompilierzeit und andere Compiler
|
||||
verbesserungen finden im Moment im nightly build statt. Von Rust gibt es im
|
||||
Abwärtskompatibilität. Verbesserungen der Kompilierzeit und andere Compiler
|
||||
Verbesserungen finden im Moment im nightly build statt. Von Rust gibt es im
|
||||
Moment ungefähr alle sechs Wochen ein Release. Rust 1.1 beta wurde zusammen
|
||||
mit dem 1.0 Release zur Verfügung gestellt.
|
||||
|
||||
|
@ -19,8 +19,6 @@ Wenn du bereits mit CSS3 vertraut bist, wirst du dir Sass relativ schnell aneign
|
||||
|
||||
|
||||
```scss
|
||||
|
||||
|
||||
//Einzeilige Kommentare werden entfernt, wenn Sass zu CSS kompiliert wird.
|
||||
|
||||
/* Mehrzeilige Kommentare bleiben bestehen. */
|
||||
@ -427,7 +425,6 @@ body {
|
||||
.gutter {
|
||||
width: 6.25%;
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## SASS oder Sass?
|
||||
@ -442,7 +439,7 @@ Du kannst beide Syntax-Optionen benutzen, gehe einfach in die Einstellungen und
|
||||
Sass kann in jedem Projekt verwendet werden, solange du ein Programm hast, um es in CSS zu kompilieren.
|
||||
Du solltest verifizieren, dass das CSS, was du verwendest, mit deinen Ziel-Browsern kompatibel ist.
|
||||
|
||||
[QuirksMode CSS](http://www.quirksmode.org/css/) und [CanIUse](http://caniuse.com) sind gute Resourcen um die Kompatibilät zu überpüfen.
|
||||
[QuirksMode CSS](http://www.quirksmode.org/css/) und [CanIUse](http://caniuse.com) sind gute Resourcen um die Kompatibilität zu überprüfen.
|
||||
|
||||
|
||||
## Literaturhinweise
|
||||
|
@ -307,7 +307,7 @@ do {
|
||||
|
||||
|
||||
// Endrekursionen sind idiomatisch um sich wiederholende
|
||||
// Aufgaben in Scala zu lösen. Rekursive Funtionen benötigen explizit einen
|
||||
// Aufgaben in Scala zu lösen. Rekursive Funktionen benötigen explizit einen
|
||||
// Rückgabe-Typ, der Compiler kann ihn nicht erraten.
|
||||
// Der Rückgabe-Typ in diesem Beispiel ist Unit:
|
||||
|
||||
@ -457,7 +457,7 @@ class Dackel extends Hund {
|
||||
}
|
||||
|
||||
// Object
|
||||
// Wird ein Objekt ohne das Schlüsselwort "new" instanziert, wird das sog.
|
||||
// Wird ein Objekt ohne das Schlüsselwort "new" instanziiert, wird das sog.
|
||||
// "companion object" aufgerufen. Mit dem "object" Schlüsselwort wird so
|
||||
// ein Objekt (Typ UND Singleton) erstellt. Damit kann man dann eine Klasse
|
||||
// verwenden, ohne ein Objekt instanziieren zu müssen.
|
||||
@ -634,10 +634,10 @@ val patternFunc: Person => String = {
|
||||
// 7. "Higher-order"-Funktionen
|
||||
/////////////////////////////////////////////////
|
||||
|
||||
// Scala erlaubt, dass Methoden und Funktionen wiederum Funtionen und Methoden
|
||||
// Scala erlaubt, dass Methoden und Funktionen wiederum Funktionen und Methoden
|
||||
// als Aufrufparameter oder Rückgabewert verwenden. Diese Methoden heißen
|
||||
// higher-order functions.
|
||||
// Es gibt zahlreiche higher-order-Funtionen nicht nur für Listen, auch für
|
||||
// Es gibt zahlreiche higher-order-Funktionen nicht nur für Listen, auch für
|
||||
// die meisten anderen Collection-Typen, sowie andere Klassen in Scala.
|
||||
// Nennenswerte sind:
|
||||
// "filter", "map", "reduce", "foldLeft"/"foldRight", "exists", "forall"
|
||||
@ -796,7 +796,7 @@ import scala.collection.immutable.{List, Map}
|
||||
import scala.collection.immutable.{List => ImmutableList}
|
||||
|
||||
|
||||
// Importiere alle Klasses, mit Ausnahem von....
|
||||
// Importiere alle Klassen, mit Ausnahme von....
|
||||
// Hier ohne: Map and Set:
|
||||
|
||||
import scala.collection.immutable.{Map => _, Set => _, _}
|
||||
@ -824,7 +824,6 @@ val writer = new PrintWriter("myfile.txt")
|
||||
writer.write("Schreibe Zeile" + util.Properties.lineSeparator)
|
||||
writer.write("Und noch eine Zeile" + util.Properties.lineSeparator)
|
||||
writer.close()
|
||||
|
||||
```
|
||||
|
||||
## Weiterführende Hinweise
|
||||
|
@ -1,7 +1,7 @@
|
||||
---
|
||||
category: tool
|
||||
category: framework
|
||||
filename: learnshutit-de.html
|
||||
tool: ShutIt
|
||||
framework: ShutIt
|
||||
contributors:
|
||||
- ["Ian Miell", "http://ian.meirionconsulting.tk"]
|
||||
translators:
|
||||
@ -22,10 +22,9 @@ Es ist verfügbar als pip install.
|
||||
|
||||
## Hello World
|
||||
|
||||
Starten wir mit dem einfachsten Beispiel. Erstelle eine Datei names example.py
|
||||
Starten wir mit dem einfachsten Beispiel. Erstelle eine Datei namens example.py
|
||||
|
||||
```python
|
||||
|
||||
import shutit
|
||||
session = shutit.create_session('bash')
|
||||
session.send('echo Hello World', echo=True)
|
||||
@ -50,7 +49,7 @@ Ians-MacBook-Air.local:ORIGIN_ENV:RhuebR2T#
|
||||
Das erste Argument zu 'send' ist der Befehl, den du ausführen möchtest.
|
||||
Das 'echo' Argument gibt die Terminalinteraktion aus. ShuIt ist standardmäßig leise.
|
||||
|
||||
'Send' kümmert sich um die nervige Arbeiten mit den Prompts und macht
|
||||
'Send' kümmert sich um die nervigen Arbeiten mit den Prompts und macht
|
||||
alles was du von 'expect' erwarten würdest.
|
||||
|
||||
|
||||
@ -79,7 +78,7 @@ example.com:cgoIsdVv:heDa77HB#
|
||||
```
|
||||
|
||||
|
||||
Es ist klar das das nicht sicher ist. Stattdessen kann man Folgendes machen:
|
||||
Es ist klar, dass das nicht sicher ist. Stattdessen kann man Folgendes machen:
|
||||
|
||||
```python
|
||||
import shutit
|
||||
@ -149,8 +148,8 @@ two.example.com:Gl2lldEo:D3FavQjA#
|
||||
|
||||
## Beispiel: Überwachen mehrerer Server
|
||||
|
||||
Wir können das obige Programm in ein einfaches Überwachungstool bringen indem
|
||||
wir Logik hinzufügen um die Ausgabe von einem Befehl zu betrachten.
|
||||
Wir können das obige Programm in ein einfaches Überwachungstool bringen, indem
|
||||
wir Logik hinzufügen, um die Ausgabe von einem Befehl zu betrachten.
|
||||
|
||||
```python
|
||||
import shutit
|
||||
@ -171,11 +170,11 @@ session1.logout()
|
||||
session2.logout()
|
||||
```
|
||||
|
||||
Hier kannst du die 'send\_and\_get\_output' Methode verwenden um die Ausgabe von dem
|
||||
Hier kannst du die 'send\_and\_get\_output' Methode verwenden, um die Ausgabe von dem
|
||||
Kapazitätsbefehl (df) zu erhalten.
|
||||
|
||||
Es gibt elegantere Wege als oben (z.B. kannst du ein Dictionary verwenden um über
|
||||
die Server zu iterieren), aber es hängt and dir wie clever das Python sein muss.
|
||||
Es gibt elegantere Wege als oben (z.B. kannst du ein Dictionary verwenden, um über
|
||||
die Server zu iterieren), aber es hängt an dir wie clever das Python sein muss.
|
||||
|
||||
|
||||
## kompliziertere IO - Expecting
|
||||
@ -232,7 +231,7 @@ der Ausgabecode dich nicht interessiert.
|
||||
|
||||
Wenn du das Argument nicht mitgegeben hättest, dann hätte dir ShutIt
|
||||
ein interaktives Terminal zurückgegeben, falls es ein Terminal zum
|
||||
kommunizieren gibt. Dies nennt sich ein 'Pause point'.
|
||||
Kommunizieren gibt. Dies nennt sich ein 'Pause point'.
|
||||
|
||||
|
||||
## Pause Points
|
||||
@ -247,7 +246,7 @@ session.pause_point('Das ist ein pause point')
|
||||
|
||||
Danach kannst du das Skript fortführen, wenn du CTRL und ']' zur selben Zeit drückst.
|
||||
Dies ist gut für Debugging: Füge ein Pause Point hinzu und schaue dich um.
|
||||
Danach kannst du das Programm weiter ausführen. Probiere folgendes aus:
|
||||
Danach kannst du das Programm weiter ausführen. Probiere Folgendes aus:
|
||||
|
||||
```python
|
||||
import shutit
|
||||
@ -276,10 +275,10 @@ Ians-Air.home:ORIGIN_ENV:I00LA1Mq#
|
||||
|
||||
## noch kompliziertere IO - Hintergrund
|
||||
|
||||
Kehren wir zu unseren Beispiel mit dem Überwachen von mehreren Servern zurück.
|
||||
Kehren wir zu unserem Beispiel mit dem Überwachen von mehreren Servern zurück.
|
||||
Stellen wir uns vor, dass wir eine langlaufende Aufgabe auf jedem Server durchführen möchten.
|
||||
Standardmäßig arbeitet ShutIt seriell, was sehr lange dauern würde.
|
||||
Wir können jedoch die Aufgaben im Hintergrund laufen lassen um sie zu beschleunigen.
|
||||
Wir können jedoch die Aufgaben im Hintergrund laufen lassen, um sie zu beschleunigen.
|
||||
|
||||
Hier ist ein Beispiel, welches du ausprobieren kannst.
|
||||
Es verwendet den trivialen Befehl: 'sleep'.
|
||||
@ -323,8 +322,8 @@ Um mehr zu erfahren, siehe:
|
||||
[ShutIt](https://ianmiell.github.io/shutit/)
|
||||
[GitHub](https://github.com/ianmiell/shutit/blob/master/README.md)
|
||||
|
||||
Es handelt sich um ein breiteres Automatiesierungsframework, und das oben
|
||||
genannte ist der sogennante 'standalone Modus'.
|
||||
Es handelt sich um ein breiteres Automatisierungsframework, und das oben
|
||||
genannte ist der sogenannte 'standalone Modus'.
|
||||
|
||||
Feedback, feature requests, 'Wie mache ich es' sind herzlich willkommen! Erreiche mit unter
|
||||
[@ianmiell](https://twitter.com/ianmiell)
|
||||
|
116
de-de/sql-de.html.markdown
Normal file
116
de-de/sql-de.html.markdown
Normal file
@ -0,0 +1,116 @@
|
||||
---
|
||||
language: SQL
|
||||
filename: learnsql-de.sql
|
||||
contributors:
|
||||
- ["Bob DuCharme", "http://bobdc.com/"]
|
||||
translators:
|
||||
- ["denniskeller", "https://github.com/denniskeller"]
|
||||
lang: de-de
|
||||
---
|
||||
|
||||
Die Structured Query Language (SQL) ist eine ISO Standardsprache zum Erstellen und Arbeiten mit Datenbanken, die in einem Set von Tabellen gespeichert sind. Implementierungen fügen in der Regel eigene Erweiterungen zur Sprache hinzu; [Der Vergleich von verschiedenen SQL Implementierungen](http://troels.arvin.dk/db/rdbms/) ist eine gute Referenz für Produktunterschiede.
|
||||
|
||||
Implementierungen bieten typischerweise eine Eingabeaufforderung, in den du die hier gezeigten Befehle interaktiv eingeben kannst. Sie bieten auch einen Weg, um Serien von Befehlen in einer Skript auszuführen. (Die Anzeige, dass du fertig mit der interaktiven Eingabeaufforderung bist, ist ein gutes Beispiel für etwas, was nicht standardisiert ist. Die meisten SQL Implementierungen unterstützen die Schlüsselwörter QUIT, EXIT oder beides.
|
||||
Einige dieser Beispielbefehle gehen davon aus, dass sie die [MySQL employee sample database](https://dev.mysql.com/doc/employee/en/), verfügbar auf [GitHub](https://github.com/datacharmer/test_db), schon geladen wurde. Die GitHub Dateien sind Skripte von Befehlen, ähnlich wie die entsprechenden Befehle unten, die Tabellen mit Daten über die Mitarbeiter einer fiktiven Firma erstellen und füllen. Die Syntax für die Ausführung dieser Skripte hängt von der verwendeten SQL-Implementierung ab. Ein Dienstprogramm, das man über die Betriebssystemeingabeaufforderung ausführen kann, ist typisch.
|
||||
|
||||
|
||||
```sql
|
||||
-- Kommentare starten mit zwei Bindestrichen. Jeder Befehl endet mit einem Semikolon.
|
||||
|
||||
-- SQL unterscheidet nicht zwischen Groß- und Kleinschreibung bei
|
||||
-- Schlüsselwörtern. Die Beispielbefehle folgen der Konvention der
|
||||
-- Schreibweise in Großbuchstaben, damit sie leichter von Datenbank-,
|
||||
-- Tabellen- und Spaltennamen zu unterscheiden sind.
|
||||
|
||||
-- Erstellen und Löschen einer Datenbank. Bei Datenbank- und Tabellennamen
|
||||
-- wird zwischen Groß- und Kleinschreibung unterschieden.
|
||||
CREATE DATABASE someDatabase;
|
||||
DROP DATABASE someDatabase;
|
||||
|
||||
-- Liste verfügbare Datenbanken.
|
||||
SHOW DATABASES;
|
||||
|
||||
-- Verwende eine bestimmte Datenbank.
|
||||
USE employees;
|
||||
|
||||
-- Wähle alle Zeilen und Spalten aus der Tabelle departmens aus der aktuellen
|
||||
-- Datenbank aus.
|
||||
-- Das Standardverhalten für den Interpreter ist die Ergebnisse auf
|
||||
-- dem Bildschirm zu scrollen.
|
||||
SELECT * FROM departments;
|
||||
|
||||
-- Hole dir alle Zeilen aus der departments Tabelle,
|
||||
-- aber nur die dept_no und die dept_name Spalten.
|
||||
-- Das Aufteilen von Befehlen auf mehrere Zeilen ist in Ordnung.
|
||||
SELECT dept_no,
|
||||
dept_name FROM departments;
|
||||
|
||||
-- Hole dir alle departments Spalten, aber nur 5 Zeilen.
|
||||
SELECT * FROM departments LIMIT 5;
|
||||
|
||||
-- Hole dir die dept_name Spaltenwerte aus der departments Tabelle,
|
||||
-- in der der Wert dept_name die Teilzeichenfolge 'en' hat.
|
||||
SELECT dept_name FROM departments WHERE dept_name LIKE '%en%';
|
||||
|
||||
-- Hole dir alle Spalten von der departments Tabelle, in der die dept_name
|
||||
-- Spalte mit einem 'S' beginnt und exakt 4 Zeichen danach besitzt.
|
||||
SELECT * FROM departments WHERE dept_name LIKE 'S____';
|
||||
|
||||
-- Wähle die Titelwerte aus der Titeltabelle, aber zeige keine Duplikate an.
|
||||
SELECT DISTINCT title FROM titles;
|
||||
|
||||
-- Das Gleiche wie oben, aber sortiert nach den Titelwerten, mit Beachtung
|
||||
-- der Groß und Kleinschreibung.
|
||||
SELECT DISTINCT title FROM titles ORDER BY title;
|
||||
|
||||
-- Zeige die Anzahl der Zeilen in der departments Tabelle an.
|
||||
SELECT COUNT(*) FROM departments;
|
||||
|
||||
-- Zeige die Anzahl der Zeilen in der departments Tabelle an, die 'en' als
|
||||
-- Teilezeichenkette des Wertes dept_name haben.
|
||||
SELECT COUNT(*) FROM departments WHERE dept_name LIKE '%en%';
|
||||
|
||||
-- Eine Vereinigung von Informationen von mehreren Tabellen:
|
||||
-- Die titles Tabelle zeigt, wer welche Jobtitel hatte, wer welche Mitarbeiter-
|
||||
-- nummer hat, von welchen Startdatum und zu welchen Enddatum
|
||||
-- Wir rufen diese Information ab, aber anstelle der Mitarbeiternummer,
|
||||
-- verwenden wir die Mitarbeiternummer als Querverweis auf die employees Tabelle
|
||||
-- um die die Vor- und Nachnamen jedes Mitarbeiters zu erhalten.
|
||||
-- (und nur 10 Reihen)
|
||||
SELECT employees.first_name, employees.last_name,
|
||||
titles.title, titles.from_date, titles.to_date
|
||||
FROM titles INNER JOIN employees ON
|
||||
employees.emp_no = titles.emp_no LIMIT 10;
|
||||
|
||||
-- Liste alle Tabellen in allen Datenbanken auf. Verschiedene Implementierungen
|
||||
-- stellen typischerweise einen eigenen Abkürzungsbefehl zur Verfügung für
|
||||
-- die aktuell verwendete Datenbank.
|
||||
SELECT * FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_TYPE='BASE TABLE';
|
||||
|
||||
-- Erstelle eine Tabelle in der aktuell verwendeten Datenbank
|
||||
-- mit dem Namen tablename1, in der die beiden Spalten angezeigt werden
|
||||
-- Es gibt viele weiteren Optionen, wie man die Spalten spezifizieren kann,
|
||||
-- wie z.B. deren Datentyp.
|
||||
CREATE TABLE tablename1 (fname VARCHAR(20), lname VARCHAR(20));
|
||||
|
||||
-- Füge eine Zeile mit Daten in die Tabelle tablename1. Dies setzt voraus,
|
||||
-- das die Tabelle so definiert worden ist, dass sie die geeigneten
|
||||
-- Werte akzeptiert.
|
||||
INSERT INTO tablename1 VALUES('Richard','Mutt');
|
||||
|
||||
-- Verändere den fname Wert zu 'John' für alle Zeilen,
|
||||
-- die einen lname Wert von 'Mutt' haben.
|
||||
UPDATE tablename1 SET fname='John' WHERE lname='Mutt';
|
||||
|
||||
-- Lösche Zeilen aus der tablename1 Tabelle,
|
||||
-- deren lname Wert mit dem Wert 'M' beginnen.
|
||||
DELETE FROM tablename1 WHERE lname like 'M%';
|
||||
|
||||
-- Lösche alle Zeilen von der tablename1 Tabelle, hinterlasse nur eine leere
|
||||
-- Tabelle.
|
||||
DELETE FROM tablename1;
|
||||
|
||||
-- Lösche die gesamte tablename1 Tabelle.
|
||||
DROP TABLE tablename1;
|
||||
```
|
@ -13,7 +13,7 @@ lang: de-de
|
||||
|
||||
Swift ist eine Programmiersprache von Apple für die Entwicklung von iOS und macOS Applikationen. Swift wurde 2014 zu Apples WWDC Entwicklerkonferenz vorgestellt und wurde mit dem Ziel entwickelt, fehlerträchtigen Code zu vermeiden sowie mit Objective-C zu koexistieren. Es wird mit dem LLVM Compiler gebaut und ist ab Xcode 6+ verfügbar.
|
||||
|
||||
Das offizielle [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) Buch von Apple ist kostenlos via iBooks verfügbar.
|
||||
Das offizielle [Swift Programming Language](https://itunes.apple.com/us/book/swift-programming-language/id881256329) Buch von Apple ist kostenlos via Apple Books verfügbar.
|
||||
|
||||
Außerdem hilfreich ist Apples [Getting Started Guide](https://developer.apple.com/library/prerelease/ios/referencelibrary/GettingStarted/RoadMapiOS/index.html), ein guter Einstiegspunkt mit komplettem Swift-Tutorial.
|
||||
|
||||
@ -210,7 +210,7 @@ default: // notwendig (um alle möglichen Eingaben zu verarbeiten)
|
||||
|
||||
:param: name Ein Name
|
||||
:param: day Ein Tag
|
||||
:returns: Ein String, der Name und Tag beinhält.
|
||||
:returns: Ein String, der Name und Tag enthält.
|
||||
*/
|
||||
func greet(name: String, day: String) -> String {
|
||||
return "Hello \(name), today is \(day)."
|
||||
@ -585,7 +585,7 @@ prefix func !!! (inout shape: Square) -> Square {
|
||||
// Aktueller Wert
|
||||
print(mySquare.sideLength) // 4
|
||||
|
||||
// Wert nach verwendung des eigenen Operators
|
||||
// Wert nach Verwendung des eigenen Operators
|
||||
!!!mySquare
|
||||
print(mySquare.sideLength) // 12
|
||||
```
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user