JuliaKurs23/chapters/first_contact.qmd

329 lines
8.0 KiB
Plaintext

---
engine: julia
---
```{julia}
#| error: false
#| echo: false
#| output: false
using InteractiveUtils
```
# First Contact
Dieses Kapitel soll beim 'Loslegen' helfen. Es läßt viele Details weg und die Codebeispiele sind oft eher suboptimal.
## Julia als Taschenrechner
```{julia}
#| eval: true
#| echo: false
#| output: false
using REPL, Markdown
function mhelp(s,n,m)
helptxt = Core.eval(Main, REPL.helpmode(s))
helpstr=Markdown.plaininline(helptxt)
print("...\n", join(split(helpstr,'\n')[n:m],'\n'), "\n...")
end;
function Tab(s)
l = filter(x->startswith(x,s), REPL.doc_completions(s))
println.(l[2:end])
return # return nothing, since broadcast println produces empty vector
end
▷ = |>
# IJulia.set_verbose(true)
```
Berechne $\qquad 12^{1/3} + \frac{3\sqrt{2}}{\sin(0.5)-\cos(\frac{\pi}{4})\log(3)}+ e^5$
```{julia}
12^(1/3) + 3sqrt(2) / (sin(.5) - cos(pi/4)*log(3)) + exp(5)
```
Man beachte:
- Potenzen schreibt man `a^b`.
- Die Konstante `pi` ist vordefiniert.
- `log()` ist der natürliche Logarithmus.
- Das Multiplikationszeichen `a*b` kann nach einer Zahl weggelassen werden, wenn eine Variable, Funktion oder Klammer folgt.
## Die wichtigsten Tasten: `Tab` und `?` {#sec-tab}
Man drücke beim Programmieren immer wieder die Tabulatortaste, sobald 2...3 Buchstaben eines Wortes getippt sind. Es werden dann mögliche Ergänzungen angezeigt bzw. ergänzt, wenn die Ergänzung eindeutig ist. Das spart Zeit und bildet ungemein:
```{julia}
lo = "lo" #| hide_line
lo ▷ Tab
```
```{julia}
pri = "pri" #| hide_line
pri ▷ Tab
```
Die eingebaute Julia-Hilfe `?name` zu allen Funktionen und Konstrukten ist sehr umfassend. Hier ein eher kurzes Beispiel:
```{julia}
?for
```
:::{.content-hidden unless-format="xxx"}
::: {.cell }
``` {.julia .cell-code}
?for
```
::: {.cell-output .cell-output-stdout}
```
search: for foreach foldr floor mapfoldr factorial EOFError OverflowError
for loops repeatedly evaluate a block of statements while iterating over a sequence of values.
Examples
julia> for i in [1, 4, 0]
println(i)
end
1
4
0
```
:::
:::
:::
## Variablen und Zuweisungen
Variablen entstehen durch Zuweisung *(assignment)* mit dem Zuweisungsoperator `=` . Danach können sie in weiteren Anweisungen verwendet werden.
```{julia}
x = 1 + sqrt(5)
y = x / 2
```
Im interaktiven Betrieb zeigt Julia das Ergebnis der letzten Operation an.
:::{.callout-note .titlenormal}
Zuweisungen sind keine mathematischen Gleichungen. Die Semantik des Zuweisungsoperators (Gleichheitszeichens) ist:
- berechne die rechte Seite und
- weise das Ergebnis der linken Seite zu.
Ausdrücke wie `x + y = sin(2)` sind daher unzulässig. Links darf nur ein Variablenname stehen.
:::
## Datentypen
Julia ist eine [stark typisierte](https://de.wikipedia.org/wiki/Starke_Typisierung) Sprache. Alle Objekte haben einen Typ.
So gibt es unter anderem die Basistypen
- Ganze Zahlen *(integers)*,
- Gleitkommazahlen *(floating point numbers)*,
- Zeichenketten *(strings)* und
- Wahrheitswerte *(booleans)*.
Den Typ einer Variablen kann man mit der Funktion `typeof()` ermitteln.
```{julia}
#| warning: true
#| error: true
for x ∈ (42, 12.0, 3.3e4, "Hallo!", true)
println("x = ", x, " ..... Typ: ", typeof(x))
end
```
Die Standard-Gleitkommazahl hat eine Länge von 64 Bit, entspricht also einer `double` in C/C++/Java.
Julia ist eine [dynamisch typisierte](https://de.wikipedia.org/wiki/Dynamische_Typisierung) Sprache.
Variablen haben keinen Typ. Sie sind typlose Referenzen (Zeiger) auf Objekte.
Wenn man vom „Typ einer Variablen“ spricht, meint man den Typ des Objektes, das der Variablen gerade zugewiesen ist.
```{julia}
x = sqrt(2)
println( typeof(x), " - Wert von x = $x" )
x = "Jetzt bin ich keine Gleitkommazahl mehr!"
println( typeof(x), " - Wert von x = $x" )
```
## Druckanweisungen
Die Funktion `println()` unterscheidet sich von `print()` dadurch, dass sie am Ende einen Zeilenvorschub ausgibt.
```{julia}
print(y)
print("...die Zeile geht weiter...")
print("immernoch...")
println(y)
println("Neue Zeile")
println("Neue Zeile")
```
Beide Funkionen können als Argument eine Liste von *strings* und Variablen bekommen. Man kann Variablen auch in *strings* einbetten, indem man dem Variablennamen ein Dollarzeichen voranstellt *(string interpolation)*.
```{julia}
x = 23
y = 3x + 5
zz = "Fertig!"
println("x= ", x, " ...und y= ", y, "...", zz) # 1. Variante
println("x= $x ...und y= $y...$zz") # Variante mit string interpolation
```
:::{.callout-note .titlenormal collapse=true icon=false }
## Wenn man ein Dollarzeichen drucken will...
muss man einen *backslash* voranstellen. Wenn man einen *backslash* drucken will, muss man ihn verdoppeln.
```{julia}
println("Ein Dollar: 1\$ und drei backslashs: \\\\\\ ")
```
:::
## Funktionen
Funktionsdefinitionen beginnen mit dem Schlüsselwort `function` und enden mit dem Schlüsselwort `end`. In der Regel haben sie eine oder mehrere Argumente und geben beim Aufruf ein berechnetes Objekt mit der `return`-Anweisung zurück.
```{julia}
function hypotenuse(a, b) # heute besonders umständlich
c2 = a^2 + b^2
c = sqrt(c2)
return c
end
```
Nach ihrer Definition kann die Funktion benutzt (aufgerufen) werden. Die in der Definition verwendeten Variablen `a,b,c,c2` sind lokale Variablen und stehen außerhalb der Funktionsdefinition nicht zur Verfügung.
```{julia}
#| error: true
x = 3
z = hypotenuse(x, 4)
println("z = $z")
println("c = $c")
```
Sehr einfache Funktionen können auch als Einzeiler definiert werden.
```{julia}
hypotenuse(a, b) = sqrt(a^2+b^2)
```
## Tests
Tests liefern einen Wahrheitswert zurück.
```{julia}
x = 3^2
x < 2^3
```
Neben den üblichen arithmetischen Vergleichen `==, !=, <, <= ,> ,>=`
gibt es noch viele andere Tests. Natürlich kann man das Ergebnis eines Tests auch einer Variablen zuweisen, welche dann vom Typ `Bool` ist. Die logischen Operatoren `&&`, `||` und Negation `!` können in Tests verwendet werden.
```{julia}
test1 = "Auto" in ["Fahrrad", "Auto", "Bahn"]
test2 = x == 100 || !(x <= 30 && x > 8)
test3 = startswith("Lampenschirm", "Lamp")
println("$test1 $test2 $test3")
```
## Verzweigungen
Verzweigungen (bedingte Anweisungen) haben die Form
```default
if <Test>
<Anweisung1>
<Anweisung2>
...
end
```
Ein `else`-Zweig und `elseif`-Zweige sind möglich.
```{julia}
x = sqrt(100)
if x > 20
println("Seltsam!")
else
println("OK")
y = x + 3
end
```
Einrückungen verbessern die Lesbarkeit, sind aber fakultativ. Zeilenumbrüche trennen Anweisungen. Das ist auch durch Semikolon möglich. Obiger Codeblock ist für Julia identisch zu folgender Zeile:
```{julia}
# Bitte nicht so programmieren! Sie werden es bereuen!
x=sqrt(100); if x > 20 println("Seltsam!") else println("OK"); y = x + 3 end
```
Es wird dringend empfohlen, von Anfang an den eigenen Code übersichtlich mit sauberen Einrückungen zu formatieren!
## Einfache `for`-Schleifen
zum wiederholten Abarbeiten von Anweisungen haben die Form
```default
for <Zähler> = Start:Ende
<Anweisung1>
<Anweisung2>
...
end
```
Beispiel:
```{julia}
sum = 0
for i = 1:100
sum = sum + i
end
sum
```
## Arrays
1-dimensionale Arrays (Vektoren) sind eine einfache Form von Containern. Man kann sie mit echigen Klammern anlegen
und auf die Elemente per Index zugreifen. Die Indizierung beginnt mit 1.
```{julia}
v = [12, 33.2, 17, 19, 22]
```
```{julia}
typeof(v)
```
```{julia}
v[1] = v[4] + 10
v
```
Man kann leere Vektoren anlegen und sie verlängern.
```{julia}
v = [] # leerer Vektor
push!(v, 42)
push!(v, 13)
v
```
:::{.callout-note icon="false" .titlenormal collapse="true" font-variant-ligatures="no-contextual" }
## Nachtrag: wie die Wirkung der Tab-Taste auf dieser Seite simuliert wurde...
```{julia}
using REPL
function Tab(s)
l = filter(x->startswith(x,s), REPL.doc_completions(s))
println.(l[2:end])
return # return nothing, since broadcast println produces empty vector
end
▷ = |> # https://docs.julialang.org/en/v1/manual/functions/#Function-composition-and-piping
pri = "pri";
```
```{julia}
pri ▷ Tab
```
:::