Transcript: Typescript und Typisierung

· Back to episode

Full episode transcript. Timestamps refer to the audio playback.

Ja, hallo liebe Hörerinnen und Hörer, willkommen beim Python-Podcast, heute Episode 54.

Wir reden heute über Types, Type-Ins und Type-Script.

Hallo.

Hallo, willkommen Dominik und...

Hallo Johannes.

Hallo zusammen.

Und hallo Stefan.

Genau.

Ja, hallo Stefan.

Auch ein Gast heute.

Genau.

Ja, wir freuen uns sehr, dass ihr alle da seid und fangen einfach mit News an, wie sonst auch immer.

Ja, würde ich schon sagen.

Was gab es denn Schönes?

Wer möchte anfangen, soll ich?

Ja, fang du mal an.

na gut, ja, also

ehrlich gesagt, das letzte Mal war nicht so lange her, daher

habe ich ja nicht so viel gesammelt. Heißt ein 3.12.1

Genau, das ist natürlich irgendwie

stand irgendwie dabei, so 400 Bugfixes

und so, also ja, sollte man wahrscheinlich mal

installieren und meine Frage dazu wäre halt

bist du jetzt schon umgestiegen

auf 3.12, weil du wolltest ja immer nur

die erste meiner Version abwarten, aber dann

auch, ja? Ja, also noch

nicht mit allen Sachen, aber mit vielen Sachen

Okay, sehr gut. Also 3.12.1

ist draufgekommen und jetzt in meinem

Systeminterpreter zum Beispiel, ist der auf 3.12.

Hervorragend.

Ja, aber ich glaube,

da war nichts, also außer Bugs

ist da nichts irgendwie passiert.

Mein Hauptproblem im Moment ist halt PyTorch oder so was,

wo es auch im Dezember einen Release gab,

dass es jetzt endlich mit 3.11 funktioniert.

Ah, ja, ja.

Ja, aber...

Ja, ansonsten genau neue Releases.

Es gab einen neuen

Ruby on Rails Release.

Ich gucke da ab und zu mal so rüber, weil ich halt

interessant finde, wie viel

tolles Zeug da passiert.

Und das ist jetzt deutlich schneller geworden,

hat irgendwie einen eingebauten Dustin-Time-Compiler

und verwendet jetzt einen ähnlichen Ansatz für den Parser,

wie Python halt auch.

Python ist ja jetzt mit irgendwie 3.9 auf dem Pack-Parser umgestiegen.

Und das ist, Ruby verwendet da jetzt was ganz Ähnliches.

Ist auch so ein rekursives Dings da, Parsen.

Ich weiß nicht, ich habe es wieder vergessen,

wie das genau heißt.

So ähnlich.

Und sie sind auch umgestiegen von Bison,

also dem Parser-Generator, auf einen anderen.

Ich habe, finde ich, schon ganz oft Lob für Ruby gehört, muss ich ehrlich sagen.

Ja, und auch bei dieser ganzen Just-in-Time-Compile-Geschichte,

da ist, glaube ich, einer der Hauptsponsoren auch Shopify.

Ja, genau.

Also es gibt ja viele große Unternehmen,

die hauptsächlich auf Ruby und Rails Moduliten basieren.

Und da kommt halt auch eine Menge Geld rein.

Und ja, Python ist ja jetzt auch dran mit diesem Just-in-Time-Compiler-Thema.

Das wäre meine News gewesen, Jochen.

Ach so, sorry.

Dann schieb's mal los.

Ja, Ende Dezember

ist wohl ein Patch in den 3.13

Branch reingekommen, wo ein JIT-Compiler

drin ist für Python. Also es ist jetzt

richtig im Plan drin, dass

Python in 3.13 einen JIT-Compiler hat.

Einen Copy-and-Patch-JIT-Compiler.

Was auch immer das bedeuten mag.

Da gab's auch angeblich eine wundervolle Diskussion

auf Reddit zu...

Ja, also

es gibt einmal die, ich kann empfehlen,

es gibt Core-PY, das ist so ein Podcast,

wo zwei der Core-Entwickler

irgendwie drüber reden. Da gibt es eine Episode

zum Just-In-Time-Compiler.

Wer sind dabei?

Shannon und Sean? Oder wie ist das?

Ne, das sind

Pablo Galindo Salgado,

der Release-Manager

auch für 3.13

und

Luca Schlanger.

Ah ja. Genau.

Die haben da einmal drüber geredet und

daher weiß ich auch, dass das

basiert hauptsächlich,

also warum man das jetzt nochmal in Angriff nimmt,

auf Geschichten, die in Lua

passiert sind. Da gab es jetzt auch irgendwelche

– ich habe jetzt wieder die

Details vergessen – aber so Papers,

die sehr, sehr interessant aussahen und

die halt vermuten lassen, dass man es relativ leicht

irgendwie auch für Python verwenden kann.

Und ja, das ist halt ein

InPython in Ruby.

Da werden überall diese Dinger jetzt gerade eingebaut.

Und hier der

wegen dem PyPy auch hier war schon

der meinte auch so,

oh, er muss jetzt mal sein

Commit-Bit

wieder hochfahren.

Wieder quasi aus...

Ja, es gab ja immer, dass die neuen Versionen

deutlich einfacher zu implementieren sind bei PyPy,

wenn das drin ist, was da

in C-Extensions irgendwie dazukommen

sollte, wollte, wenn ich das richtig verstanden

hatte damals. Ja, also

jedenfalls, der macht da jetzt auch mit.

Ah, cool. Das wird auf jeden Fall spannend.

Schnelles Python.

Ja, genau.

Es gab dann ein Issue zu, wo dann einer

von Netflix oder so in relativ freundlichem Ton zun schrieb irgendwie so ja also das macht bei uns sehr viel Arbeit und irgendwie das war jetzt alles irgendwie nicht so g und ich hab dann

geguckt, der hat dann auch irgendwann beschrieben, welche Issues

die da reingelaufen sind und das war halt zum Beispiel auch

einer von den Dingern, in die ich

da reingerannt bin

und

ja, genau, der meinte dann

so, tja, also sauberer wäre es gewesen, wenn man

das Paket irgendwie umbenannt hätte oder so

und das wollten sie aber nicht machen

Und dann haben sie gesagt, nee, das geht auch so oder geht so.

Und das ging alles nicht.

Und das war relativ furchtbar.

Also gerade wenn man eine Library ist,

hat man damit halt ein großes Problem,

weil man nicht kontrollieren kann,

was in der Applikation, die einen benutzt,

halt irgendwie für eine Pydentic-Version ist.

Und zum Beispiel FastAPI hat damit auch ein Riesenproblem gehabt.

Und wie die das dann letztendlich gemacht haben,

ist, sie haben halt so einen Flag eingeführt, Pydentic V2,

und machen dann jetzt gerade so was wie if Pydentic V2.

Bäh.

500 Zeilen eingerückt,

irgendwie Kompatibilitätsleer

und dann Else und dann sonst.

Und das haben sie an mehreren Stellen.

Das ist wirklich absolut schrecklich.

Naja, aber so sieht es halt aus.

Dieses Update war nicht

wirklich reibungslos,

sondern da haben viele Leute irgendwie eine Menge

Schweiß gelassen.

Also nicht nur ich.

Okay, also gut, wenn man es nicht zu sehr

drin hat. Ich habe tatsächlich auch

zwischendurch noch auf eins dependen müssen,

weil da so bei zwei Sachen nicht so ging,

was jetzt irgendwie geht, aber ja.

Ein bisschen nervig.

Johannes, hast du noch was?

Nee, also in der

TypeScript-Welt gibt es sowas nicht.

Aber jetzt kann man uns über TypeScript-Versionen

unterhalten.

Apropos, ich habe gehört, dass ein neues Buch erschienen

in der TypeScript-Welt. Echt, was?

Das ist mir ganz neu.

Ich glaube, das muss der Stefan mal so ein bisschen erzählen.

Ist das jetzt mein Intro oder was?

Ja, das war die Software-Überleitung.

Ja, genau.

Ich habe das jetzt total spannend gefunden, weil es wird ja immer so gemunkert, dass im Web-Bereich gibt es ja quasi alle drei Minuten irgendeinen neuen Fachbegriff oder irgendeinen neuen Bibliothekennamen oder irgendein neues JavaScript-Framework, das irgendeinen abstrusen Namen hat, mit dem sich alle nachher irgendwie auseinandersetzen müssen.

und das ist jetzt das zweite Mal,

dass ich so in diese Python-Ecke reinschaue

und denke mir, hey, komm, das ist ja da genau das Gleiche.

Den ersten

Namen, den ich erkannt habe,

das war fast API,

weil tatsächlich, das ist spannend, ich bin

jetzt mit, seit

vier, fünf Monaten bei uns in der

Firma mit einer Gruppe Python-Developern

unterwegs, Data Scientist, ganz klassisch,

du hast einen Data Scientist

und

das Tool der Wahl ist Python, die Bibliotheken sind da,

das übliche mit Longchain, Pipa Pro

für diese ganze LLM

Sache. Und das war so

mein erstes

Intro in dieser Python-Welt und ich bin schon

massiv gescheitert daran, dass ich den Package-Manager

auswähle,

der passt. Da gibt es ja dann

Conda, Anaconda,

Pep oder sind das ganz andere?

Keine Ahnung. Also wie gesagt, das ist ja schon wieder

vorbei. Aber ich

weiß, dass ich fast immer noch langen, langen

Gesprächen mit unseren Python-Devs

in unser Architektur-Diagramm eingetragen

habe für irgendeinen Server, den wir

gemacht haben. Genau, also das war eben das

Erste, wo ich mir gedacht habe, so, da kenne ich mich

jetzt aus, bei FastAPI, da kann ich mitreden.

Funktioniert

Multithreaded, aber

nicht Async. Ist das richtig?

Nee, also kann

man wahrscheinlich so betreiben, wenn man wirklich will,

aber nee, es ist tatsächlich Async.

Also unter FastAPI liegt

normalerweise, so würde ich jetzt mal

sagen, wenn man das so betreibt, wie es gedacht

ist halt

Stalett beziehungsweise UV-Corn

und das ist halt sozusagen die

LibUV, also das ist halt

eine Adaption von LinnUV, was halt auch

unter der Event-Loop bei Node.js

liegt halt für Python.

Ja, und

also ist halt quasi genauso schnell

dann auch und ist Async.

Cool. Das war die

zweite, war dann, dass ich

versucht habe,

über Pyro 3

eine Brücke zwischen

zwischen Async Rust und Async Python

einmal zu schreiben. Das war spannend.

Das war richtig cool. Also was mich da

beeindruckt hat, und mit dem habe ich

nicht gerechnet, ist, dass

das Foreign-Francish-Interface von Python

ja fantastisch ist. Also du

hast dort dein kompiliertes

SO-Modul dazu und du kannst auf

die Objektliste zugreifen

und kannst die Identifier herauslesen.

Also das Kompilieren vom Rust-Code

war auf jeden Fall anspruchsvoller,

als wir nachher die Symbole in

Python zu loben und zu verwenden. Das war

richtig, richtig beeindruckend. Also

coole Sache, möchte ich mir auf jeden Fall

mehr anschauen. Aber das ist es.

Das sind meine Python-Kenntnisse.

Ja, aber ich finde auch,

das Benutzen von Python ist halt das, was so Spaß

macht. Also

High-Level-Interface, ich glaube, ist sehr gut geeignet.

PS3, auch ein cooles Beispiel.

Da gibt es die meisten Sachen die es irgendwie kann Ich glaube was es nicht kann ist irgendwie Iteratoren ausspucken richtig oder so oder Generatoren ergeben Ja das wird wahrscheinlich schwierig sein Das kann ich mir gut vorstellen Keine Ahnung Da ist dieses Typsystem von Rust halt doch sehr sehr eigen und

sehr schwierig in andere

Sprachen zu integrieren.

Nehme ich mal an. Ja, aber

ich hatte ja als News ja auch quasi noch ein bisschen Werbung

gemacht für dein Buch. Vielleicht willst du dazu noch irgendwie kurz

was sagen? Ja,

Dankeschön. Danke für diese Überleitung.

Ich habe tatsächlich

in den letzten Jahren

TypeScript-Bücher geschrieben.

Das erste Buch, das ich geschrieben habe,

war in 2020

TypeScript in 50 Lessons,

das beim Smashing Magazine Verlag

rausgekommen ist, das als

angenehmer,

unaufgeregter Einstieg

in TypeScript als Typsystem

auf JavaScript gedacht ist.

Das Zielpublikum waren

Entwicklerinnen und Entwickler, die

JavaScript schon kennen, sich dort

auch schon wohlfühlen und jetzt merken

jetzt müssen sie TypeScript verwenden, brauchen die Info, warum man das erstens überhaupt haben will

und zweitens, wie das jetzt so richtig funktioniert und warum es da so viel Syntax gibt

und warum das so kompliziert ausschaut und versucht, das grundlegende System,

Typsystem runterzubrechen auf einfach zu verdauende Lektionen.

Genau, das war das Ziel von dem Buch. Das habe ich dann zufälligerweise in 50 Lektionen geschafft.

Das war ein Riesenspaß. Das war quasi mein Corona-Projekt, mein erstes Lockdown-Projekt.

Wobei, stimmt nicht, ich habe es zwischen dem ersten und dem zweiten Lockdown tatsächlich das meiste geschrieben.

Das ist auch tatsächlich ein schickes Buch. Das sieht auch super aus, also von außen.

Wir wissen das, weil wir dieses Buch auch alle haben.

Ja, tatsächlich.

Zwar als Python-Entwickler, was natürlich auch schon was heißt.

Alles ohne die Kamera gehalten. Das macht mich irrsinnig happy.

Ihr kennt sich das nicht vorstellen. Das sind diese unglaublich schönen Momente,

wenn man sieht, dass das Buch tatsächlich an Leute kommt und Leute das verwenden.

Also die Lesepäntchen gesehen herrlich spitze.

Und die Optik ist wirklich ganz, ganz besonders,

weil das war eigentlich auch ein Grund,

warum ich mit Smashing Magazine zusammenarbeiten wollte.

Die haben einfach irrsinnig viel Liebe zum Detail

und versuchen wirklich sehr individuelle Bücher zu machen,

haben eine wunderschöne Typografie, das sauber zu lesen ist

und verzetteln sie dann in kleinen Finessen so stark.

Und ich habe zum Beispiel, das Cover wurde gestaltet von Rob Draper, den habe ich tatsächlich in Düsseldorf kennengelernt, auf der Björn Tellerrand, der als Künstler die Intro-Grafiken zu den Golden Globes gemacht hat, für Nike und BMX-Fahrräder bzw. Schuhe designt hat.

und der mich gefragt hat, hey, so,

E-Mail geschrieben, hey, der war aber das cool,

möchtest du mein Buch designen? Ja, passt.

Und ich habe gedacht, hey, wow, cool, ich hoffe, er kostet jetzt

nicht eine Million oder so.

Er hat tatsächlich dann

das Buch gestaltet,

also versucht

er mit diesem Kapitel

in Lays ein bisschen

das Ganze zugänglich zu machen,

freundlich zu machen, das war uns ganz, ganz

wichtig und die Person,

die nachher, also die Ari, die nachher das Ganze

gesetzt hat und versucht hat, ein Produkt daraus zu machen, hat dann auch recherchiert

und hat zum Beispiel das Lesebändchen, das rote Lesebändchen in der Farbe bestellt von

den roten Unterlinien in Visual Studio Code.

Das heißt, das ist der gleiche Farbton und so tief ins Detail geht es dort und das ist

halt einfach absolut herrlich für mich, der praktisch nur den Text beigetragen hat, dass

du siehst, wie andere Leute sich so investieren in dieses Projekt und versuchen, gemeinsam

oder irgendwas Cooles draus zu machen,

da kriege ich heute noch Gänsehaut.

Das ist ja für mich so,

ich weiß, es ist mein Buch,

aber es ist nicht nur mein Buch.

Da sind so viele Leute daran beteiligt gewesen.

Es war ein irrsinnig cooler Effort

von so vielen Menschen

und das macht mich einfach jedes Mal wieder glücklich,

wenn ich dann sehe,

dass das Leute auch so sehen,

sie das in die Bücherregale stellen

oder das Beste, was du machen kannst,

hast du einen Zoom-Call,

stell es in den Hintergrund

und schick mir ein Foto von dem Zoom-Call.

Das ist das Allerbeste.

Das macht mir die größte, größte Freude.

und es hat eine Freude für mich gemacht,

wie er ein Interview

für sein Startup gemacht hat,

auf einmal sehe ich, hey, da ist mein Buch im Hintergrund,

herrlich, also macht

Riesenspaß.

Das war das erste TypeScript-Buch, ich habe dann noch ein zweites

TypeScript-Buch geschrieben, das ist erst

im September rausgekommen, also ist noch ganz, ganz frisch,

das ist das TypeScript-Cookbook,

das jetzt mit O'Reilly

veröffentlicht worden ist,

das war praktisch

eine Auftragsarbeit, also O'Reilly hat

zu diesen Acquisition-Editors, die suchen halt noch potenziellen Autoren,

schlagen denen Buchprojekte vor oder schlagen vor, hey, möchtest du zu dem Thema was schreiben?

Und sie haben gesagt, sie wollen ein TypeScript-Buch veröffentlichen in diesem Stil

wie TypeScript in 50 Lessons, ob ich mir vorstellen kann, noch ein solches zu schreiben.

Und am Anfang haben wir gedacht, nein, das geht nicht, ich habe jetzt schon ein Buch geschrieben,

ich habe halt einfach eine gewisse Ansicht, eine gewisse Stimme,

eine gewisse Idee zu dem Ganzen habe aber gedacht naja wenn du sie so reil probierst oder mal kurz ein Inhaltsverzeichnis unterschreibst wie du dir ein zweites Buch vorstellen kannst Und gerade habe ich 100 weitere Eintr gehabt innerhalb von drei Stunden

Also ich bin mir am Nachmittag hingesetzt und habe gedacht,

ups, wow, da ist ein Buch da.

Und bin mit denen in einen Vertrag gegangen

und habe dann versucht,

den Nachfolger vom TypeScript in 50 Lessons Buch zu schreiben.

Wenn du in TypeScript in 50 Lessons lernst,

wie das Typ-System funktioniert,

lernst du im TypeScript-Book alle Dinge,

die schief gehen können.

Dinge, die, wenn du wirklich Programme damit schreibst,

wo du merkst, hey, da passt gerade was nicht,

da spielt das Typsystem nicht so mit,

wie ich mir das denke, beziehungsweise

brauche ich halt irgendeine Technik oder irgendein

Prinzip oder irgendein

Pattern, das ich anwenden kann,

um einem gewissen Problem entgegenzukommen.

Im Moment, ich dachte, so Typen hast du damit,

nichts mehr schiefgehen kann. Und mit

sicheren statischen Typen sind die

Sprachen immer ganz besonders gut.

Genau, da beschreibt man nur mehr Programme, die

nur mehr funktionieren und man hat keine Bugs

mehr und es ist super happy.

Ja, genau.

Ich bin eine super Überleitung

tatsächlich auf das Thema, was wir heute machen wollen, oder?

Ja.

Ganz herzlichen Dank, dass du heute da bist, Stefan.

Das freut uns sehr.

In Paisen haben wir von Typen auch schon das eine,

andere Mal am Rande gehört.

Ja, wir haben diese Episode immer lange vor uns hergeschoben,

weil wir uns nie ausreichend vorbereitet gefühlt haben.

Weil es halt so ein großes Thema ist.

Es gibt auch eine ganz große Anti-Fan-Gemeinde

in Paisen für Types.

irgendwie. Ja, es gibt auch viele,

die das nicht so mögen, ja.

Wie seid ihr da so drauf?

Also habt ihr jetzt Typen schon

in eurem Python-Code drinnen oder ist das eher noch so

das Buch mit sieben Siegeln, das ihr nicht

öffnen wollt? Annotationen nutze

ich persönlich sehr gerne, insbesondere dann, wenn

ich mit anderen Menschen arbeite, um einfach

so zu dokumentieren, was macht das denn

überhaupt. Das heißt aber nicht,

dass das immer stimmt, was da steht.

Das ist aber gefährlich.

Ja, das ist ein gefährliches Spiel.

Ja, also ich verwende sie auch schon und ich habe halt ein Projekt mal so komplett irgendwie annotiert, einfach nur auch, weil ich wissen wollte, wie schwierig ist es denn nun, wie weh tut es denn irgendwie.

und ja, das ging schon,

aber es war auch, also ich habe

da jetzt nicht so wahnsinnig viel

irgendwie

Nutzen rausziehen können, aber

ich hatte auch vorher neben dem Ding halt auch schon

100% Test-Coverage, insofern

war da einfach wahrscheinlich nicht mehr so viel

zu,

ja auch das habe ich

ja gemacht, um es mal gemacht zu haben,

als das halt wirklich Nutzen hatte.

Ich habe tatsächlich in den Projekten bei mir jetzt Enforced MyPy

Pre-Commit-Hook, das ist auch

schon, da gehe ich ziemlich vielen Leuten auf die Nerven.

Aber...

Da kannst du überall Objekt hinschreiben, oder? Das zählt doch auch.

Ja, okay. Also da sind die

meisten nicht draufgekommen.

Oh, da habe ich jetzt ein Geheimnis verraten.

Hups.

Annie oder Anna.

Also ich bin

beeindruckt von der 100% Test Courage.

Also ich bin

leider Gottes der faulste Tester.

Dieseits der Donau.

Also das ist...

Ich sage immer, also ich habe

diesen Spruch gehabt, wie ich noch in einer

Agentur gearbeitet habe, dass ich sage, ja, getestet wird beim

Kunden, wenn es in Production ist,

es soll reichen, aber

ich, keine Ahnung,

liegt es an der Software,

die ich schreibe oder an der Rolle, in der ich bin,

ich bin sehr, sehr selten

jemand, der wirklich ausgiebige

Testsuit schreibt und da,

also das ist, glaube ich,

also auch schärfenhaupt, das ist, glaube ich,

meine größte Schwäche.

Ja, 100% Courage ist auch schon sehr

ich finde es beeindruckend, wirklich.

Ja, das haben wir in dem Projekt, in dem ich bin, auch 100%

Branch Coverage sogar.

Und TypeScript.

Es ist ja oft so, dass man das so ein bisschen

als gegensätzliche

Pole ansieht, sag ich mal. Die einen machen

Typen und die anderen machen Testing.

Und das ist schön, Stefan, dass du das jetzt bestätigt hast,

aber

Ich bin quasi das Typen

Paradebeispiel.

Ich meine, das Ding ist,

JavaScript und Python haben ja

die gleiche Eigenschaft, dass beides

in der Praxis dynamisch

typisierte Sprachen sind.

Sprich, natürlich gibt es Typen, sonst könntest du mit den ganzen

Werten nichts anfangen. Es ist aber relativ

egal, was das für ein ist. Du kannst dann

ein Number oder ein Integer

einer Variable zuweisen und im nächsten

Schritt dann String und keiner regt sie auf

und keiner beschwert sie und es funktioniert halt einfach.

Oder du kannst verschiedene Typen mischen.

Du kannst ein String mit einer Zahl kombinieren.

Nein, das geht in Pandas.

Okay, cool. Dann seid ihr schon mal einen Riesenschritt weiter

als in JavaScript.

Das ist ja das große Problem an JavaScript, oder?

Dass du solche implizite Konversionen drin hast.

Ja, also das heißt ja immer weak getyped versus strong getyped,

aber ich weiß nicht, ob das irgendein Sinn ergibt.

Ja, dynamic versus static, aber diese ganzen Bezeichnungen sind ja alle nur so ein bisschen.

Also die schöneren Bezeichnungen sind meiner Meinung nach statisch und dynamisch,

wo du einfach weißt, okay, definierst du den Typen im Vorhinein

oder wird er definiert durch die Verwendung?

Weak und strong, also schwach und stark

ist eine sehr

schwache Bezeichnung

meiner Meinung nach.

C zum Beispiel hat ein

statisches Typsystem, aber ein sehr, sehr

schwaches. Ob du jetzt einen Character hast oder ein

Integer oder irgendwas anderes, es ist einfach

komplett wurscht. Also du kannst alles damit machen.

Und kannst auch hin und her wechseln und kannst auch

Bitfiddling mit allem möglichen Scheiß machen.

Genau, genau, genau. Wundervolle Bühne.

Und vor dem ist das

Statische eigentlich das Wichtige, weil es eine bisschen andere

Herangehensweise ans

Programmieren

voraussetzt. Du machst dir

einfach mehr Gedanken über

die mögliche Wertemenge

einer Variable, bevor

du einen Wert zuweist. Das schließt

jetzt nicht aus, dass du sagen kannst, hey, du

bekommst einen Typen durch Typ-Inferenz,

das mache ich sehr, sehr gerne, weil ich sage, hey,

diese Variable x ist 3

und dann weißt du, dass das ein Number oder Integer oder was auch immer

ist. Das geht natürlich auch, das machen auch

moderne Programmiersprachen sehr, sehr, sehr gerne.

Grundlegend,

dass du halt mit wenig Annotationen machen kannst.

Nichtsdestotrotz

definierst du Verträge

zwischen Bausteinen deines Codes, zwischen den Functions,

zwischen Methoden in deinen Klassen etc.,

in denen du sagst, du erwartest aber jetzt diesen Wertebereich

und nichts anderes und du lässt auch nichts anderes zu.

Und TypeScript ist meiner Meinung nach doch sehr, sehr spannend,

weil TypeScript versucht, eine sehr dynamische,

dynamisch typisierte Programmiersprache

und generell sehr dynamische Programmiersprache wie JavaScript

in einer gewissen Art und Weise zu formalisieren.

Also das Ziel ist ja jetzt nicht dort eine komplett neue Programmiersprache zu definieren oder zu entwickeln, sondern auf Basis einer bestehenden irgendwie ein Regelwerk zu finden, damit alle beteiligten Programmierinnen und Programmierer irgendwas zu diskutieren haben und wissen, was da eigentlich vor sich geht.

Nichts ist schlimmer, wenn du ein halbes Jahr, nachdem du dein Programm geschrieben hast, wieder zurückgehst und dich fragst, was war denn diese Variable X nochmal? Also was habe ich mir da eigentlich gedacht? Und dann hast du irgendeine fette Wurst an Code und musst herauslesen, was du eigentlich damit machst.

und also das ist was, was

mich immer komplett

verwirrt hat, wie

ich habe da nie ein funktionales

Programmierparadigmen ausprobiert,

viel mit asynchronen Promises gearbeitet in Not,

irgendwelche dynamischen Objekte

gehabt, wo ich ständig neue Keys hinzugefügt habe

und wieder entfernt habe und das war kurz

und effektiv und schnell und schön

und drei Monate später habe ich nicht mehr

gewusst, was ich dort mache, wenn ich das Programm heute lese,

ich kenne mich nicht aus und ich würde es auch heute

nicht mehr so machen, einfach weil

weil, also gut österreichisch, sorry, Graut und Ruben einfach zusammenschmeißen

und hofft, dass am Ende alles funktioniert.

Und das ist gut für kleine Skripte, das ist gut, wenn du irgendwie geschwind was runterheckst.

Aber wenn ihr wirklich mit einem Team versucht, reale Software zu machen,

dann ist das, glaube ich, die niedrigste Schwelle, die du hast,

um zu dokumentieren, was jetzt von deiner Software und von den Nutzern deiner Software überhaupt erwartet wird.

Und ich glaube, deswegen sind Typen so wichtig.

Und deswegen, glaube ich, sind Typen auch in Python sehr, sehr interessant, weil du ja da die gleichen Voraussetzungen hast. Also du musst ja wissen, was erwartet jetzt deine Funktionen und je mehr Bibliotheken, die du hast. Wie gesagt, ich wäre schon gesagt, ich bin jetzt in diesem Long-Gen und LLM-Wahnsinn irgendwie gefangen. Da hast du sehr, sehr komplexe Objekte, die du hin und her schickst. Woher sollst du wissen oder woher soll ich wissen, der kein Python schreibt, sondern nur lest, was da jetzt eigentlich erwartet wird und was ich da rauskriege.

Das finde ich auch, also das tatsächlich so als Dokumentationstyp

für Python ist das, was ich auch am häufigsten

gerne mag, also in kleinen Closures,

in kleinen Methoden oder Funktionen irgendwie

die Argumente so zu annotieren,

dass beim Riesen klar wird, was denn

der Mensch da haben möchte, der

diese API bereitstellt,

dass ich das irgendwie zusammengebaut kriege oder so, oder

verstehe, was er denn da braucht oder sowas.

Das sehe ich anders.

Ja, ich weiß nicht so.

Aber das hätte ich ja heute hier.

Ja, genau.

Also ich finde, dass das Argument, was der Dominik bringt, das stimmt, wenn man nur simple Funktionen hat. Also wenn man wissen will, ob da jetzt ein Integer oder ein String rein muss. Und man hat vier Parameter und die haben alle simple Typen.

Aber für mich fällt es auseinander, wenn die Typen

komplex werden, weil dann hast du

irgendwelche benannten Typen, die

irgendwelche interne Struktur haben,

die völlig opak ist und dann hast du

17 verschiedene Varianten davon

und am Ende weißt

du genauso wenig, was da rein muss und was

nicht. Und

das hat alles so seine Grenzen.

Ja, ich habe letzte

Woche mit einem Freund telefoniert

und haben uns auch kurz über

Type Annotations unterhalten und der meinte so

ja, schön und gut und ich sehe die Vorteile und so.

Ich finde es einfach irgendwie hässlich,

weil irgendwie...

Das ist ein gutes Argument.

Die IDE, ja, okay.

Das ist eigentlich alles gesagt.

Ästhetisch ist immer das Argument.

IDE kann damit was anfangen oder so,

aber wenn man das jetzt anguckt,

dann hat man bei den ganzen modernen Libraries heutzutage,

dann hast du da irgendwie Funktionen

und da hast du pro Zeile einen Parameter weil da kommt immer der Name des Parameters dann kommt halt die Typannotation die einem nicht viel sagt und dann kommt nochmal ein Kommentar

der erklärt, was die Typannotation einem eigentlich

sagen will und das dann

so untereinander. Dann meinte er so, das erinnert mich total

an C-Code aus den 80ern. Ich weiß

nicht, ich mag das nicht.

Das ist nicht peinlich.

Aber ich muss,

diesen Argument höre ich auch häufig, wenn man jetzt so bei den

alten, zum Beispiel

übernächste Woche wieder, oder

Das nächste, ich weiß nicht.

Das nächste, ja.

Auch hier aufs Python-User.

Und das nächste, nächste Mittwoch.

Das nächste Woche, ja.

Ja, ja.

Genau, gehen.

Da gibt es dann die alteingesessenen,

die sagen auch immer so, ah.

Immer nur AXE-Quarks, Sternchen, Sternchen.

Nein, das nicht, aber.

Ja, ja, aber das ist schon so ein Punkt,

mit dem viele Probleme haben, ja.

Ich kenne genug Python,

dass ich den Witz mit AXE-Quarks verstanden habe.

Dann gehörst du schon zu den Oberen.

Ja, also gut.

Ich bin immer sehr kritisch,

wenn es darum geht, dass man die Ästhetik

bewertet, weil

ich schreibe sehr viel in Rust. Rust ist eine

sehr unästhetische Sprache. Du hast quasi

hey, wie viel Syntax kann

Programmiersprache vertragen? Und Rust sagt ja.

Also, her damit.

Aber dafür ist mir halt in Rust

zu jedem Zeitpunkt absolut

hundertprozentig klar, was passiert. Und das ist

halt auch ein Vorteil,

den man nicht leugnen kann.

Gerade wenn man in Teams arbeitet. Und da nehme ich halt

die paar Annotationen, die ich da habe, einfach hin

und

irgendwas hat jetzt da geblinkt,

ich bin kurz rausgekommen

und verstehe zumindest, was passiert.

Und ich muss ganz ehrlich sagen, was ich rein jetzt sehe

von dem, was

wie Python

Typings umsetzt,

ist das eh sehr

minimalistisch. Also da kann man sich noch

weit, weit mehr verausgaben. Also ich finde das gar nicht

aber so hässlich.

Ja, ich

finde das Problem ist halt,

dass diese Typsysteme

oft zu weit getrieben werden

und das treibt dann Blüten.

Ja, also für alles und jedes und nochmal die letzte.

Genau, für alles und jedes und es muss dann alles ein benannter

Typ sein und das geht dann,

also ich habe hier

ein Beispiel aus der

Apple-Dokumentation, da gibt es einen Typen,

der heißt CN Label Contact Relation

Younger Cousin, Mother, Siblings, Daughter or Father,

Sisters, Daughter.

Ja. Ist ein Typ.

Ja, ob man den jetzt braucht oder nicht.

Auf der anderen Seite

ein Beispiel aus der .NET

Bibliothek.

Die Links sind dann alle in den Show Notes.

Da gibt es eine Methode, die heißt Run.

Die hat 30 Argumente.

31. Das erste ist ein

Object, das heißt Makro. Das zweite ist ein Object,

das heißt Arc1.

Das dritte ist ein Object, das heißt Arc2.

Und so geht es weiter bis Arc30.

Grandios. Da bringen mir die Typen nichts.

Da sagen mir die Typen nicht,

was das macht.

Und zwar in beide Richtungen nicht.

Und es gibt halt da diese Fetischisten, die sagen,

du musst aber überall benannte Typen drin haben

und du musst das Typsystem vollständig

ausnutzen.

Und das geht mir genauso auf den Senkel wie die alten

Herren, die dann sagen, nein,

Typ-Annotationen ist

ekelhaft und hässlich und wie in den 80ern.

Irgendwo in der Mitte ist dieses Maß

und

Du hast mich gerade an etwas Wunderbares erinnert.

Ich bin ja

in einer Java-Welt groß geworden.

und habe gelitten.

Ich auch.

Ich komme aus der Nähe von Linz

und direkt auf dem anderen Bergerl

gegenüber wohnt

einer der Erfinder vom

Spring Framework. Also wir kennen uns,

unsere Kinder gehen gemeinsam in die Schule und solche Sachen

und da gibt es eine Klasse, das ist

die Has This Type Pattern Try

to Sneak in Some Generic or Parameterize

Type Pattern Matching Stuff Anywhere Visitor.

Und das ist

fantastisch. Also bei uns

in der Firma, ohne Java-Developer,

bei uns in der Firma, ohne Java-Developer,

diese Weißkin-Monitore, aber nicht,

dass sie irgendwie dort mehrere Fenster

nebeneinander hinkriegen, sondern ich sage immer, das ist,

damit sie die Klassennamen ohne

Zeilenhundbruch durchstehen können.

Und das ist natürlich,

das ist Mumpitz, das ist ganz klar.

Ich denke, man muss die ganzen Sachen immer ein bisschen

pragmatischer sehen

und halt auch einen richtigen

Nutzen oder wissen, welchen

Nutzen man daraus zieht. Das gilt für

alles in der Softwareentwicklung, meiner Meinung nach.

Ja, das ist ein Dankzeug.

Und um das geht es eigentlich Und gerade in TypeScript also gerade auch in meinem Buch gibt es ein paar Beispiele drinnen da kommen sie schon richtig richtig vorausgekommen Da gibt es irrsinnig m Werkzeuge wie String Literal Types oder Tappel Variadic Das sind Dinge wo ich mir denke

Wahnsinn, dass das überhaupt geht.

Also beeindruckend technisch, dass das geht.

Aber die Use-Cases

dafür sind halt stark limitiert und man muss wirklich überlegen,

ob das dafür steht. Und ich habe dort

drei Lektionen, wo wir

ein funktionales

Programmiertool wie

Currying versuchen, auf drei

sehr, sehr komplexe Orten umzusetzen und sagen,

aber überleg dir, ob diese Typen jetzt das gerechtfertigen, was du da als Funktion schreibst

oder ob du nicht lieber eine Funktion nimmst, die viel, viel weniger kann,

aber genauso einfach zu verwenden ist und die einfach zu typisieren ist,

mit der du besser die Typinformationen rauskriegst.

Und das stelle ich dann auch so zur Diskussion.

Also man muss halt immer abwägen können, wie rechtfertigst du den Einsatz dieses Werkzeugs

und wie weit treibst du das?

Ja, ich glaube, das ist tatsächlich gar nicht so einfach herauszufinden.

Ja, und ich glaube aber, dass da noch ein anderes Problem dahinter ist. Und ich bin sehr froh, Stefan, dass du da gesagt hast, dass du gegen Tests bist oder gegen große Testcoverage. Und du hast jetzt gerade eben so ein bisschen deinen Ansatz beschrieben, wie du Programme schreibst. Und du hast das gesagt, was meiner Meinung nach ganz wichtig ist. Du hast gesagt, du fängst an, ein Programm zu schreiben und weißt noch nicht, wie es am Ende ausschauen wird.

und das geht mir genauso

und das ist einer der Gründe,

warum ich

Python mag,

weil mir das die Freiheit gibt,

da so explorativ rumzugehen, ohne

mir groß Gedanken machen zu müssen,

wie es denn jetzt sauber zusammenpasst

und ich glaube, dass das ein Programmierstil ist,

ich nenne das exploratives Programmieren,

ich muss so ein bisschen diesen Space

erkunden, muss so ein bisschen sehen, was kann

ich, was schaffe ich, was mache ich

und das ist halt mein Stil,

Ich gehe da rein und sage, jetzt machen wir erstmal irgendwas. Es gibt aber auch Leute, die da vielleicht mathematischer rangehen und die sagen, okay, ich habe hier einen Plan und eigentlich auf dem Papier habe ich es ja schon hingeschrieben, dann kann ich auch die Tests zuerst schreiben, weil ich weiß ja schon, was das machen soll. Ich weiß ja schon, wie es am Ende ausschaut. Oder ich kann gleich die richtigen Typen reinschreiben.

Ja, da müssen wir uns ja das Akkord nicht verändern und einfach Type-Driven-Development, eine neue Instanz starten.

mir.

Und

ja, das sind glaube ich

einfach zwei verschiedene Arten zu

programmieren, die eben verschiedene Dinge

eher bevorzugen.

Es ist tatsächlich

glaube ich auch ein bisschen von der Sprache abhängig, weil

also ich glaube Python und JavaScript

unterstützen ja diese Art des explorativen

Programmierens sehr, sehr stark. Einfach eben

in dem sie die Typen auch entfernen.

Du kannst sie wirklich einfach mal herumprobieren und schauen,

was rauskommt und schauen,

wie weit du mit

deinen Ideen kommst.

Was ich spannend finde, also ich bin

jetzt seit einigen Jahren auch sehr, sehr stark in Rust drin,

ich habe das jetzt schon erwähnt, und sorry, das ist der

klassische Rust-Nutzer, nicht ständig

sagen, dass er Rust verwendet, aber

es ist halt wirklich so. Die Sprache macht einiges

sehr, sehr richtig. Du hast in Rust eine sehr

stark typisierte

Programmiersprache mit einem fantastischen

Typsystem. Das ist grandios,

dass das so funktioniert,

wie es funktioniert. Das heißt, du kannst dir gar nicht

leisten, dass du einfach nur mehr schaust,

hey, was, wo

Wo kommst du mit deinen Wertebereichen überhaupt am Ende hin?

Aber trotzdem schafft es Rust, dass du explorativ arbeiten kannst,

weil einfach die Mittel, die zur Verfügung gestellt werden, so zugänglich sein können,

weil die Typen, die vor Hause schon drinnen sind, so entgegenkommen sind.

Das heißt, du kommst mit ein paar Basistypen aus der Standardbibliothek

und den üblichen Wertebereichen schon sehr, sehr weit,

bevor du dir selbst deine eigenen Strukturen und Interfaces, nenne ich es jetzt einmal,

auseinander überlegen musst.

Und das ist sehr, sehr spannend. Es ist aber

trotzdem ein anderer Wert des Programmierens.

Also das

Endresultat schaut auch dann

anders aus. Also ich mag das aber auch gerne,

so Models oder so Dataclasses

irgendwie zu bauen und dann zu gucken, hey, was sind das

denn überhaupt für Objekte und dir halt dann direkt zur

Annotation zu verwenden, das ist so

strukturell sehr klar.

Nein, es schließt sich auch nicht aus.

Also es ist,

ich denke mir,

die Gefahr liegt wahrscheinlich, dass man sich auf

eines komplett verschreibt.

Auch das, was der

Johannes wieder gesagt hat, ganz richtig ist,

es ist am Ende des Tages

ein Werkzeug und es muss irgendeinen

Job erfüllen.

Und wenn das gut funktioniert, dass du

dir vorher Gedanken darüber machst, welche Daten

du benötigst, dann ist das absolut legitim

meiner Meinung nach.

Ich finde es gerade so

angenehm. Wichtig ist, dass

die Sprache mit der du arbeitest, das unterstützt.

Ja, ich glaube auch eben.

Aber ich meine, das hat natürlich mal einen Preis,

weil es halt zusätzliche Komplexität unter Umständen halt auch einführt

und es dann halt vielleicht auch unzugänglicher macht.

Also worauf ich eigentlich hinaus will, ist,

naja, je nach Use Case kann es halt unterschiedlich nützlich sein.

Also wenn man halt zum Beispiel eben in einem Team an einer gro Software schreibt dann kann es halt sein dass es sehr viel bringt auch irgendwie m viele H zu errichten

bevor irgendwie Code ...

Du willst quasi gar nicht, dass die Entwickler irgendwas machen.

Ja, das ist leider halt eine Strategie,

das ist schwer zu unterscheiden von ...

Man versucht, Fehler zu vermeiden,

bevor sie dann produktiv gehen,

zu bloß nicht deployen, was dann halt auch viele Leute machen,

was halt irgendwie auch blöde Konsequenzen hat unter Umständen dann.

weil also viele Sachen, also man hat dann zum Beispiel

nicht nur ein Staging-System, sondern noch so

drei andere oder vier andere und führt immer

mehr hinzu, sodass man bloß nicht nach

Produktionen deployen muss.

Ich habe zwei Abteilungen bei uns kennengelernt,

die haben Reployment-Release-Zyklus so

alle sechs Monate.

Ja, genau, in den sechs Monaten passiert halt auch

nichts, aber ja, ist halt

vielleicht auch irgendwie ein Konflikt mit anderen

Zielen. Hast du etwa diesen

Artikel über Move Fast and Break Things gelesen,

der kürzlich rausgekommen ist?

Ja, genau.

Ja, richtig.

Und genau,

also an der Stelle macht es ja vielleicht,

wenn man in so einer Situation ist,

sehr viel Sinn da,

von den Leuten zu verlangen, dass sie sich erst Gedanken machen

und dass halt man versucht, möglichst viele Fehler

zu fangen, bevor sie halt

in der Produktion aufschlagen, weil

da ist es halt viel teurer, sie halt zu entfernen

als, aber es kann

halt total anders sein, wenn jetzt jemand zum Beispiel

und das ist halt eine der Stärken bei

Python, bei JavaScript auch

ein bisschen anders,

dass es halt vor allen Dingen auch von Leuten benutzt wird,

die sich selber gar nicht als professionelle Programmierer sehen würden,

sondern die eher sagen würden,

naja, ich bin eigentlich eher so Data Scientist

oder ein Analyst oder sowas.

Oder halt irgendwie jemand,

der irgendwie, keine Ahnung, Roboter irgendwie dazu bringt,

irgendwie lustige Dinge zu machen oder sowas.

Oder Teilchenbeschleuniger.

Oder Teilchenbeschleuniger, also solche Sachen, genau.

Und ich will gar nicht jetzt irgendwie Typtheorie verstehen

oder irgendwie, keine Ahnung,

auch Unit-Tests.

Und da sind wir auch bei einem Ding, wo die Sachen

so ein bisschen ähnlich sind. Also ich dachte auch lange Zeit

irgendwie,

Unit-Tests sind was ganz anderes und

Typisierung

ist ein anderes Ende

von einem Spektrum und ich bin eher so Team-Test.

Aber inzwischen denke ich so, naja, das ist schon

relativ ähnlich auch. Ich meine, auch Unit-Testing

ist halt so eine Sache, die man sich erst irgendwie

erschließen muss und für manche Leute macht

es einfach, wenn man halt irgendwie so

in einem Jupyter-Notebook Sachen macht,

Und ja, manchmal macht es schon Sinn, das zu testen, aber für viele Leute ist es auch nicht, lohnt es sich, weiß ich nicht, ob es sich wirklich lohnt, da so tief einzusteigen. Und aber ich meine, klar, wenn man jetzt große Software im Team entwickelt, dann klar hat man Tests und eine CI-Pipeline und weiß ich nicht, diesen ganzen Kram halt.

Ja, das Stichwort da ist doch Programming by Contract, oder? Und das ist halt eine Möglichkeit, so einen Contract zu schreiben. Aber ich bin da in so einem Zwiespalt. Einerseits bin ich total genervt von solchen Typsystemen, die dann sehr präzise sind. Ich bin auch mit Java aufgewachsen, Stefan, also ich zähle deinen Schmerz.

und dann

wirkt man sich ab und macht ein Pair

aus int und

string und dann weißt du aber nicht, wie du an den zweiten

drankommst und ach, das ist alles ganz

schön. Aber auf der anderen

Seite gibt es nicht

die Möglichkeit zu sagen, ganz triviale

Sachen zu sagen. Zum Beispiel hier muss eine

Zahl rauskommen, die immer größer ist als 0.

Oder immer kleiner als 0. Größer als 0 geht ja tatsächlich

noch, aber kleiner als 0 kannst

du nicht sagen. Du kannst nicht sagen, hier muss was rauskommen,

was zwischen 0 und 1 liegt.

und das ist irgendwie so

eine weirde Sache.

Ich bin da so im Zwiespalt. Ich hätte gerne

keine Typsysteme, aber wenn ich Typsysteme hätte,

hätte ich gerne so welche, die so exakt sind,

dass ich sowas sagen kann

und dass mir dann auch der Compiler sagen kann,

Moment, hier rufst du eine Funktion aus mit einer Zahl,

die zwischen 0 und 1 sein kann,

aber die muss zwischen 0 und

minus 1 sein.

Nee, das ist nicht Validierung, sondern das ist

nee, das sind sogenannte Value Types, das kannst du auch

in ein Typsystem reingießen, wenn du das möchtest.

Ja, das ist quasi keine Sprache.

auch tatsächlich irgendwelche Bytes liegen,

die von einer CPU ausgelesen werden.

Also das,

wenn dir das

Typsystem das erlaubt, dass du dort

irgendwas zwischen minus 1 und plus 1 zum Beispiel

definierst oder mein Gott,

eine ganze Zeit zwischen 25, was auch immer,

dann schiebst du die

Validierungen nur an eine andere Stelle.

Ja gut, aber das

macht man mit dem Typsystem generell, oder?

Also ich meine, sobald der TypeScript-Compiler durch ist,

ist er weg. Das ist

sehr richtig, genau. Das ist sehr richtig.

Ich glaube, in Python genauso, wenn ich mich nicht täusche.

Ja, generell.

In Python sind die Annotationen erstmal gar nichts.

Genau, das ist in Python auch so leicht anders.

Das wissen ja auch viele Leute.

Ja, das ist ganz, das ist halt, wenn man...

zu den praktischen Dingen kommt, die halt damit problematisch

sind. Also ich bin ja häufiger auch irgendwie

in unterschiedlichen

Firmenkontexten da so unterwegs und

das, was ich in letzter Zeit

halt häufig sehe, ist halt sowas wie

Leute annotieren halt

irgendwie ganz viel, aber

sie haben

keinen statischen Type-Checker, der da drüber

laufen würde und in Python ist halt auch keiner eingebaut,

was vielleicht auch nicht so gut ist

und man müsste da, und dann

mache ich dann sowas wie, ich lasse mal MyPy drüber

laufen und die Leute verwenden alle

TypeDict und sowas und denken halt, ja, das

überprüft jetzt, ob meine ganzen Werte da so

meine ganzen Werte

in dem Dict halt so den richtigen

Typ haben und so.

Und Python selber macht da gar nichts.

Das überprüft überhaupt nichts. Das ignoriert

die Annotationen einfach. Ich lasse dann

MyPyte rüberlaufen und kriege dann so 400 Fehler.

Und dann denke ich mir so, okay, ja, also

du hast da schön deine Annahmen darüber, wie die ganzen Typen

aussehen, dokumentiert, aber die sind halt leider alle falsch.

Das stimmt überhaupt gar nicht.

Und ja, da denkt man sich, warum hat man

sich überhaupt die Mühe gemacht. Also es ist halt irgendwie

Ja, wie ist denn

der Zustand der Entwicklungsumgebungen

in Python?

Kommt drauf an. Also auch die

hängen halt daran, ob du

MyPy zum Beispiel als Static Tideshaper

Extension richtig konfiguriert hast.

Ja, und ob dann auch

MyPy die Stubs halt

lesen kann, die halt da notwendig sind

oder halt auch nicht.

Aber viele IDEs behandelt es doch auch selber schon.

Ja, ja, genau. Da gibt es ja auch

dann, ich weiß gar nicht jetzt,

bei VS Code

dann normalerweise verwendet wird.

MyPy ist eine Extension.

Ja, aber ich meine, wenn jetzt zum Beispiel einfach nur das...

Also IntelliJ macht das selber.

Ja, die haben einen proprietären, dann gibt es irgendwie MyPy,

klar, und es gibt halt

noch PyWrite und

der Language Server für Python.

Kann es sein, dass der selber

von Microsoft in TypeScript

geschrieben ist? Ich glaube schon.

Ja, es ist nämlich spannend,

weil ich denke,

TypeScript hat da einige

richtige Entscheidungen getroffen auf dem Gebiet.

Die ihr jetzt

alle angesprochen habt, was kompliziert

und was komplex in Python ist,

nämlich,

dass die Sprache dir zwar ein

Typsystem anbietet,

cool, aber eigentlich nichts damit macht,

sondern du brauchst eh nur einen extra Typchecker

und anscheinend wie bei den Package-Managern

gibt es dort auch mehrere, wo du

dir dann noch aussuchen kannst, welcher gefällt dir jetzt

und welcher passt zu dir

und so weiter und ich finde das grandios, dass es

Auswahl gibt, keine Frage, aber es erhöht natürlich

auch die Komplexität.

Und TypeScript hat,

TypeScript selbst ist ja eigentlich

mehrere Dinge. Es ist zum einen einmal

ein Typsystem, cool, also wie werden

Typen geschrieben, definiert, wie

sind sie im Zusammenhang. Es ist auch ein

Typchecker dabei,

also der TypeScript-Compiler

TSC macht in erster Linie mal

Typechecking, aber

kompiliert dann auch tatsächlich JavaScript-Code,

den du ausführen kannst. Also es gibt so jetzt

Proposals, dass du auch Typ-Annotationen

irgendwann einmal in JavaScript schreiben können solltest,

ähnlich wie in Python, wir sind dort einfach von der Runtime ignoriert.

Aber da sind wir noch nicht, also da kommen wir erst hin.

Das heißt, du brauchst auch den Compiler.

Das heißt, wir haben ein Typ-System, Typ-Checker, Compiler

und noch auch, ganz, ganz wichtig, eine Integration in Editoren

und Entwicklungsumgebungen.

Und das war eigentlich, also dieser gesamte Tooling-Aspekt rundherum,

nicht nur das Typ-System anzubieten, sondern auch Werkzeuge anzubieten,

dass du nachher zu validen JavaScript-Code kommst und du deine Fehler siehst,

und die Fehler auch sofort in deinem Editor und deiner IDE dargestellt werden,

sind meiner Meinung nach genau die Punkte,

die noch auch den, unter Anführungszeichen,

Ziegelszug von TypeScript auch zu verantworten gehabt haben.

Weil ohne dem hast du halt nur die Hälfte der Dinge.

Du brauchst halt irgendwie alles, damit du sauber entwickeln kannst.

Und wenn ich mir denke, dass ich Visual Studio Code aufmache,

wo TypeScript schon drinnen ist,

und ich mache irgendein JavaScript-File auf

und das läuft im Hintergrund schon der TypeScript-Compiler

und checkt meinen JavaScript-Call

und versucht zu inferieren und zu verstehen,

was ich schon geschrieben habe, ohne

eine einzige Typ-Annotation.

Und ich kriege aus dem raus schon

Autocomplete und die ersten

Warnings, dass vielleicht irgendwas nicht ganz

rund läuft

und schief geht. Das ist so viel

wert, ohne dass ich eine Zeile TypeScript

schreibe, wo ich mir denke, ja, das ist eigentlich

eine richtig gute Idee gewesen.

Ja.

Da kann Python sich, glaube ich,

auch noch eine Scheibe abschneiden.

Da gibt es noch so ein paar Löcher.

Wenn ich jetzt sage,

ich installiere PyCharm oder wie auch immer,

welche Idee, und die kommt schon

mit einem Typinterpreter oder

einem Typechecker mit, das wäre natürlich

göttlich nett, dass du einfach sagst,

du brauchst nicht mehr die Typernotation schreiben,

aber die Idee hat irgendeinen

Typechecker schon per Default drinnen.

Wahrscheinlich schreiben sie ihn selbst, weil

Chatprints schreiben sie irgendwie selbst.

Haben sie.

Dann werde ich schon.

Der von Jetbrains ist aber der ist super gut Das ist einer der Gr warum man PyCharm verwendet weil die halt da die beste Typ haben Man merkt schon dass es unter Java ist

Aber das können sie.

Das sind sie richtig, richtig gut.

Schon wieder Rust.

Für Rust haben sie auch einen eigenen geschrieben.

Die ganze Welt verwendet Rust Analyzer.

Außer du nimmst Rust Rover von JetBrains,

dann ist da ein eigener drinnen.

Sie haben auch

Recht damit.

Also das ist halt alles richtig gut integriert in die Werkzeuge, die sie zur Verfügung stellen.

Ja, auch ein zusätzlicher Effekt, den das hat, dass halt quasi bei Python halt der statische Type-Checker halt nicht so wirklich zur Sprache dazugehört, ist halt auch, dass bei TypeScript ist es halt so, dass was sich sozusagen in der TypeScript-Sprache tut, auch immer sofort verfügbar ist.

halt dann, und das ist bei Python

nicht so, weil die

statischen Type-Checker vor allen Dingen von den großen

Gebäuden gebaut werden, halt nicht

MyPy, Dropbox, ich weiß nicht, ob die

immer noch da so hauptsächlich dran sind, aber dann gibt's noch

einen von Google, es gibt noch Pyright,

die hängen sowieso

immer so ein bisschen in den Versionen hinterher,

weil sie ihre Code-Basis

sowieso nicht an der aktuellsten Version halten können,

weil sie das gar nicht schaffen, weil das einfach zu viel Arbeit

ist. Das heißt,

normalerweise bei MyPy hängst du halt immer so

eine Version irgendwie von dem, was die

Sprache eigentlich kann, zurück, was halt

auch total doof ist einfach.

Du musst dich auch noch darauf einigen,

welches Subset des Typsystems du jetzt

verwendest.

Ja, genau.

Da kann ja gar nichts schief gehen.

Ja,

das ist ja keine Tester.

Das TypeScript-Own-Management

ist ja stark in der Kritik,

sehr keine Frage.

Also das ist einfach ein schwieriges Problem.

Ja, und das ist aber einfach ein schwieriges Problem.

Also ich glaube tatsächlich, dass TypeScript einfach dadurch, dass es eine jüngere Sprache ist,

gewisse Fehler vermeiden konnte, die man halt vor 20 oder 25 oder 30 Jahren machen musste mit den ganzen alten Sprachen.

Aber manche Sachen sind halt immer noch nicht gelöst und Version Hell gehört halt dazu.

Wobei ja auch sagen, dass TypeScript ist schon historisch gewachsen.

Also du merkst schon die dunklen Flecken der Vergangenheit und versuchst sie zu ignorieren. Das ist halt so. Das passiert halt. So wie Sachen verwendet werden, hast du nachher die Probleme.

Ja, und das muss sich ja auch an JavaScript orientieren. Also es muss ja JavaScript-kompatibel sein und da kriegst du halt viel, sag ich mal, Historie.

Ja, ein kleines bisschen Programmiersprachen-Historie mitgeliefert.

Ja.

Ich wollte gerade nochmal auf Java ein,

wo wir das gerade hatten.

Das ist leider schon ein bisschen drüber,

aber davon wieder weg.

Da hatte ich nämlich auch noch so eine schöne,

da habe ich letztens was sehr Schönes

gelesen,

dass halt

einer der Autoren,

auch von der Sprachspezifikation

von Java, hat halt

irgendwann mal so geschrieben

zu den Generics, also dass sie

Generics eingeführt haben, also ja,

das war irgendwie ein Fehler.

Und dann hat er irgendwie noch,

in dem Buch selber findet man auch irgendwo so eine sehr schöne

Fußnote,

wo halt quasi die

Annotation von

Inam,

Inam ist auch ein Partner ein Problem, aber

in Java halt auch,

und Inam ist halt

irgendwie definiert

als, ich such grad, ob ich das hier finde, ah ja genau

ist eine

generische Klasse definiert als Inam

Spitze Klammer T Extens Inam

Spitze Klammer T Klammer zu Klammer zu

also diese rekursive

Definition ist halt so ein bisschen

schwierig zu verstehen

wir haben inzwischen aufgegeben, es zu versuchen

Leuten zu erklären, es gibt irgendwie

Spezialisten, die uns versichert

haben, über Typtheorie

uns versichert haben, dass das schon alles okay ist und kein

Problem und wir sollen uns einfach nicht so viel

Gedanken drüber machen, was

wir sehr gerne annehmen.

Das Spannende ist ja bei den Java

Generics, dass die

als einziges Element

im Typsystem von Java

keine

Auswirkungen auf die Gestaltung

der Laufzeituobjekte haben. Also das sind

auch so,

nach dem Compile-Schritt wird das einfach entfernt

und nie wieder angesehen.

Und das ist halt das Beeindruckende

daran. Also das war halt auch so,

oh shit, das brauchen wir jetzt, wir müssen das jetzt machen

im Release 1.5, glaube ich war das.

Und das war die einfachste und

unproblematischste Art, wie wir dazu kommen.

Und

alle Implikationen, die das hat,

die werden bis heute mitgezogen. Du kannst quasi

generische Klassen nie

wirklich optimieren. Geht einfach nicht.

Was halt spannend ist weil die hast du halt Du hast Generics drin Deswegen werden auch oft nur in der Standardbibliothek das generische Object verwendet

anstatt dass du einen generischen Typ-Parameter hast.

Was ich mit Innamen sein kann, weiß ich sowieso nicht.

Ich habe das gesehen bei unseren Kollegen

und das ist kein Innamen.

Ich finde das eigentlich jetzt ein guter Zeitpunkt,

um nochmal so ein bisschen zu erklären,

worum es überhaupt geht und was da alles so drin ist.

Wir sind jetzt auch schon auf so einem relativ hohen Fluglevel

unterwegs, aber wir haben auch

viele Menschen,

die uns zuhören, die vielleicht noch gar nicht wissen,

was denn ein Generic überhaupt ist

und vielleicht sollten wir das einmal kurz

ja,

jetzt kriegen sie es halt mal gesagt.

Ja.

Im IFCenis gibt es auch Generics

in Python.

Ja, genau.

Wovon geht das?

Ja, also das ist ja,

also diese Generics in den

Typ-Annotationen, das ist ja

wirklich nur sehr instruktiv,

nur sehr so

vage gesagt,

da ist die Erasure ja

noch viel größer.

Johannes,

was ist denn bitte ein Generic?

Ein

Generic ist eine Spezialisierung

eines Typen anhand eines

anderen Typen und das klassische Beispiel ist da

die Java-Liste. In Python

hast du ja eine Liste, die

dynamisch typisiert ist, das heißt, wenn du eine Liste

hast, kannst du da eine Zahl reintun und einen String

und eine

komplexe Zahl und ein Objekt und noch

eine Liste. Das ist immer sehr unterhaltsam,

wenn ich das in den

Seminaren mache, wenn ich den Leuten

Programmieren beibringe, die vielleicht schon mal

eine Programmiersprache gesehen haben oder die

schon was davon gehört haben. Dann zeige ich hier so,

jetzt kannst du da, du kannst noch eine Liste auch reintun

oder Dictionary kannst du auch einfach in deine Liste

reintun. Und

in Java geht das nicht. In Java hat jede

Liste einen Typen. Das heißt, du kannst,

wenn du einfach nur List

sagst, dann meinst du List von Object.

Das heißt, alles, was du da reintun kannst, ist Object.

Aber du kannst

diese Liste spezieller

gestalten, indem du eben diesen

Generic-Mechanismus verwendest und sagst,

du hast jetzt nicht eine Liste von Object, sondern

du hast eine Liste von String.

Das heißt, der Compiler weiß an bestimmten

Stellen, dass dieser Typ, den du da

hingeschrieben hast, der vorher vielleicht nur ein

Platzhalter war,

in TypeScript verwendet man dann oft T oder K oder V,

das ist auch in Stefans Buch

kommt es mehrmals vor,

dass du dann eben zu einem bestimmten Zeitpunkt diesen generischen Typen ersetzt durch einen konkreten Typen und sagst,

okay, ich habe jetzt hier nicht eine Liste von Objects, sondern ich habe ganz klar eine Liste von String.

Und dann kann der Compiler oder eben das Typsystem überprüfen, dass du da tatsächlich lauter Strings drin hast.

Der Code, den du da ausführst, ist genau der gleiche, aber du hast jetzt eben einen spezifischen Typen für eine Liste von Strings gemacht.

und das hat gewisse Vorteile, zum Beispiel

wenn du da ein Objekt rausholst,

kriegst du dann halt eben nicht nur ein generisches

Object zurück, sondern du kriegst dann tatsächlich

einen String zurück.

Das ist der große Vorteil, den Java davon hat,

dass du diese Accessor-Methoden hast,

die dir die spezifischen Sachen

rausgeben.

War das korrekt erklärt, Stefan?

Ist cool.

Super, genau das.

Gott, Experte.

Ich sage ja nicht, ich bin nie Experte, ich bin einfach nur

aufgehoben und schreibe den ganzen Mist auf.

Ja gut, aber das macht dich zum Experten.

Aber nein, das beschreibst du ziemlich gut.

Also du kannst mit Typ-Parametern

dir die Entscheidung auf den tatsächlichen Typen

für später aufheben.

Das ist das, was dort passiert.

Und eben so sagst du,

dann wird das halt eine Array-List von String

oder eine Array-List von Integer

und du substituierst diesen Typ-Parameter

mit einem konkreten Typen

und kriegst nachher auch solche konkreten Typen

wieder retour.

In manchen Programmiersprachen

kannst du dann auch noch so Dinge wie

Constraints oder Bounds angeben,

wo du eben sagst, hey, du hast dort

jetzt einen beliebigen Typparameter, ja,

aber er muss einem gewissen

Subtypen entsprechen. Das heißt, er muss

eine gewisse Funktionalität zur Verfügung haben

oder muss

also TypeScript

ist ja strukturell

typisiert, was bedeutet,

dass du einfach sagst, hey, solange die Methoden

dort sind und solange die Properties

dort sind, passt schon, muss nicht

den gleichen Namen haben, muss nicht in irgendeiner Hierarchie sein,

sondern Hauptsache, schaut irgendwie

so aus, wie das eine, was

ich da erwarten würde. Und dann haut das schon hin.

Und dann kriegst du halt

zum einen die Sicherheit, dass du nicht

irgendwelche Typen reingibst, die nicht damit funktionieren

würden.

Und zum anderen

kriegst du halt noch mehr Informationen

über deinen Typ noch heraus, wenn du ihn dann vermeidest.

Wie macht man das denn in Python? Protokolle?

Doch, das ist in Python, das ist halt

drei Achtung Gründer auch so, oder kann man

das so machen? Man kann auch nominal

typisiert das Ganze machen, aber

da geht das jetzt auch, genau, mit Typing

Protocols

geht das auch.

Ja, genau, und dann...

Habt ihr das schon mal irgendwo gesehen Ja ich verwende das Bevor es jetzt Ja ja Also ich finde das eine gro Idee aber ich habe es noch nie irgendwo verwendet gesehen Ja ja doch Also ich kenne es

auch vor allen Dingen aus dem

Fluent Python

Buch von Luciano

Ramallo.

Und der hat sich auch

mit diesem Typisierungsthema

stark beschäftigt und hat dann diverse Fehler

in der TypeShed

Repository, wo halt

die ganzen, wo auch die Standardbibliothek von

Python genau

annotiert ist, hat er

da gefunden und viele

davon konnte er fixen mit

diesem Structural Typing

Ansatz. Also

Fehler im Sinne von halt

die Annotationen waren halt

False Positives oder halt

False Negatives möglich. Auch sehr

interessant, wenn man sich halt anguckt,

welche Fehler sind häufiger?

False Positives sind

viel, viel häufiger bei Typ-Annotationen

als false negatives. Also in

der Python-Standard-Bibliothek waren es

irgendwie achtmal so häufig.

Was halt auch ein Hinweis darauf ist, dass es halt

für Leute wichtiger ist, dass halt die,

also false positive heißt,

eine Annotation hat gesagt, nee,

du kommst hier nicht rein, das ist irgendwie,

du bist nicht der richtige Typ.

Dein Typ ist hier nicht gefragt.

Sozusagen, obwohl es

eigentlich doch okay gewesen wäre.

Und also offenbar

es ist halt irgendwie so mehr opportun

irgendwie auf der Seite von strikter

zu sein, zu irren, als umgekehrt.

Was ja auch so ein bisschen vielleicht

damit zusammenhängt, welche Leute das

vor allen Dingen gut ist, nämlich die, die halt versuchen

wollen, möglichst viel da draußen zu halten

und wenn sie ein bisschen zu viel draußen halten, ist es besser

als was durchzulassen, was halt dann

irgendwie knallt zur Laufzeit.

Das wäre dann voll snaggert.

Ja, genau.

Und ja,

der hat das

also lange erklärt

in dem Buch und da habe ich das halt quasi

her und ja, ich finde das

eigentlich sehr nett, weil damit kann man im Grunde genau das gleiche

machen wie ein TypeScript mit diesen Intersection

und Union Types,

was ja auch irgendwie so, das ist halt so

sehr cool eigentlich, dass das

geht und das geht halt

wenn man jetzt so mit

Abstract Base Classes das Ganze macht und Nominal

geht das halt nicht so richtig

und aber

Das Problem ist, wenn es zu Nominal arbeitet,

dass du auf dem Schlag eine Hierarchie aufbaust,

auch wenn die implizit ist durch die Basistypen,

die du definierst.

Und das kannst du sehr schön und elegant umschiffen,

indem du sagst, hey, alles, was ich erwarte,

ist einfach nur, dass das Ding so ausschaut

oder diese Werte und Eigenschaften hat,

die ich an dieser Stelle erwarte.

Methodennamen, Rückgabewerte, Propertytypen etc.

Und ich sage mal, ein Programmiersprache wie JavaScript

wäre gar nicht anders zu typisieren gewesen

oder es wäre gar nicht möglich gewesen, die anders zu typisieren, als wie mit einem strukturellen Typsystem,

weil sonst praktisch kein Code mehr funktioniert hätte, den du irgendwie geschrieben hast.

Und das war eben auch so ein Designprinzip von TypeScript, dass sie sagen, hey, wir wollen

bestehenden JavaScript-Code unterstützen und mögliche Fehler herausfinden

und nicht einfach nur aufgrund von einem arbitrer

geschaffenen Hierarchiekonstrukt sagen, das passt oder passt nicht.

und ich glaube,

es kann man gut vorstellen, dass das Python auch

stark hilft.

Definitiv.

Ja, das ist jetzt also seitdem,

ich meine, ist das auch, glaube ich,

in Go ist das ja auch so,

die Interfaces in Go verhalten sich im Grunde auch so.

Genau, du implementierst

implizit Interfaces, wenn die Methodensignatur

gleich ist, genau.

Dann bist du kompatibel zum Interface.

Ja.

Ja, und

ich verwende das tatsächlich.

Ich glaube auch, das ist eigentlich sozusagen das,

wo es dann anfängt, Spaß zu machen.

Weil ehrlich gesagt, mit den Hierarchien,

Klassenhierarchien und so, das ist nicht so

meine Vorstellung von Spaß.

Ja, also,

du hast ganz recht, Johannes.

Ich glaube, es war Johannes.

Ja, genau, das ist das, was natürlich passiert.

Du hast Klassen und dann hast du Hierarchien davon

und dann benutzt du die und fertig.

Das ist dem Konstrukt zu schulden.

Und der Konstrukt hat auch nichts dafür.

Das ist halt einfach so.

Nee, und das liegt halt auch nahe.

Du hast schon diese Hierarchie und dann benutzt

du sie halt auch weiter. Du hast schon die Struktur, also nehmen wir sie.

Ja.

Ja, ja. Aber das ist dann eben das

Problem, worauf du dann triffst.

Du kommst an eine Stelle, wo du weißt,

hier muss ich jetzt eigentlich nur addieren,

aber der Typ, den du verlangen musst, ist halt

irgendein ganz Wilder oder ein ganz

Abgefahrener oder irgendeiner, der wo ganz

anders in der Hierarchie drin ist.

Was mir sehr

gut gefällt am

Python-Typ-System, was ich gesehen habe, nur durchs

drüberfliegen, ist dieses New-Type-

Konstrukt, wo du sagen kannst, hey, es gibt schon

einen bestehenden Typen und

der ist vielleicht sehr, sehr freigiebig, der ist vielleicht

ein Integer-String oder was auch immer, aber da kannst du ihm

noch dieses eine Label verschaffen, damit du jetzt

nicht irgendwelche unterschiedlichen Integer-Werte

durcheinander kriegst oder irgendwelche Objektwerte,

die...

die ähnlich sind, durcheinander kriegst.

Weil strukturelle Typsysteme funktionieren halt immer bis zu dem Grad,

wo du sagen musst, hey, aber dieses eine Ding will ich da jetzt nicht herinnen haben,

weil ich erwarte doch etwas anderes und kann das durch das Typsystem nicht so ausdrücken.

Mach das Newtype, dann wird es explizit und dann kannst du genau sagen,

hey, an dieser Stelle erwartest du etwas, was so ausschaut,

aber es muss doch etwas anderes sein.

Und das finde ich eigentlich ganz brauchbar.

Das ist, genau, das benutze ich genau für diesen Use Case,

dass man halt

oft quasi sowas

zum Beispiel Integer möchte man

einschränken von der Range, aber das kann man im Typsystem

nicht so richtig ausdrücken und ich finde, dann reicht

oft schon, um den gleichen Effekt zu haben,

im Newtype einzuführen, also wo ich

das dann halt zum Beispiel aktuell brauche, ist halt

ich habe halt ein Jahr und ich weiß, dieses Jahr

ist halt nur von 2025 bis

2040 oder irgendwie sowas

und

mir reicht im Grunde, wenn

ich

mache das gar nicht über das Typsystem, dass diese Range dann

sozusagen abgesichert wird. Aber allein,

dadurch, dass ich sage, ich definiere

den NewTypeYear,

der halt eigentlich ein Int ist,

kann mir der TypeChecker sagen,

wenn ich irgendwie mal ein anderes Int da

reingesteckt habe, was ich nicht mal als Ja

irgendwo anders deklariert habe,

und kriege dann sozusagen den Effekt, dass wenn da irgendjemand

irgendwas reinsteckt, was kein Ja ist, dann

gibt es halt auch, sagt der

TypeChecker halt schon, okay, nee, das sieht

nicht gut aus. Und so

kann man sich halt das sozusagen so ein bisschen

herbeiemulieren, dass man

irgendwie damit auch überprüft, ob das

inhaltlich Sinn macht.

Aber noch cooler wäre es natürlich,

wenn du auch die Werte angeben könntest.

Entschuldigung, Stefan.

Weißt du?

Ja.

Also gerade mit dem, also

in TypeScript kannst du das ein bisschen. Du kannst

teilweise Werte

oder geringere Wertbereiche

definieren. Also in TypeScript ist das

Spannende, wie in jedem Typsystem,

Du hast Wertemengen und du definierst ja nur, ob dieser eine Wert, den du hast, jetzt in diese Menge passt oder nicht.

Das sind sehr große Mengen zum Teil, String, Number oder alle Objects.

Zum Teil sind sie halt auf deine Objekttypen heruntergebrochen, wo du sagst, diese Kombination an Properties, die gewisse Typen haben, erlaubst du dort oder nicht.

Du kannst aber auch sagen, hey, nicht dieser einzige oder einzelne konkrete Wert,

die Zahl 1, der String Stefan, was auch immer, kann auch als Typ gelten.

Das heißt, du kannst einen Wert haben, wo du sagst, alles, was diese Variable annehmen darf, ist der Wert 1.

Und das klingt am Anfang doof, weil was machst du mit einer Variable, die nur 1 sein kann?

Du kannst es schenken.

Aber du kannst noch diese Literal-Types oder Value-Types,

wie es du benannt hast, Johannes, kombinieren mit anderen Value-Types

und kannst dann zum Beispiel alle validen Augenzahlen eines Würfels darstellen.

Eins oder zwei oder drei oder vier oder fünf oder sechs.

Also damit hast du schon einen sehr engen Wertebereich definiert

und weißt noch aus, wenn ein Wert da reinkommt,

dann hat er garantiert eine dieser sechs Zahlen.

Und das ist spannend, das kannst du auch mit Strings machen.

Und was halt dann wirklich elegant ist, ist, dass du zum Beispiel Strings mit gewissen Pattern definieren kannst.

Du kannst sagen, hey, du erlaubst alle Strings, die mit ON anfangen,

weil du gerade dein Eventsystem implementierst und du hast halt ON-Click, ON-Key-Down, ON-Key-Press, was auch immer.

Das heißt, es muss mit on anfangen und nachher muss der erste Buchstabe unbedingt ein Großbuchstabe sein. Solche Strings akzeptierst du, andere akzeptierst du nicht. Da kannst du wirklich sehr elegant Wertebereiche definieren, mit denen du korrekte Werte angibst, mit denen du auch über deine Werte diverse Aussagen treffen kannst, die dir nachher helfen, die aber jetzt nicht so übermäßig komplex sind.

Dass du jetzt sagst, hey, das ist jetzt viel zu viel Aufwand, das zu definieren.

Mein Lieblingsbeispiel ist immer noch HTTP-Methoden,

Get, Post, Delete, was auch immer, oder HTTP-Error-Codes.

Da gibt es 70 um den Dreh.

Ich weiß jetzt nicht, ob es 201 gibt, ob es 217 noch gibt, weiß ich nicht.

Das kann mir dieser Union-Typ sehr, sehr schön sagen.

Und dann bin ich mir sicher,

dass ich den richtigen

HTTP-Status-Code meiner Response schicke

und brauche

nicht großartig überlegen, ob ich

noch im richtigen Wertebereich bin oder nicht.

Ich muss mich einmal

korrigieren. Ich habe eben nachgelesen, Value-Types

ist nicht das richtige Wort.

Das bezieht sich auch auf etwas anderes.

Das wird als Abgrenzung

zum Reference-Type verwendet.

Also ob man einen Wert oder eine Referenz hat Aber das Konzept das hast du gerade sehr sch erkl Vielen Dank Stefan Das ist auch in Kapitel 4 beschrieben von meinem Buch und da bist du ja noch nicht

Das haben wir vorhin schon festgestellt.

Ich habe noch nicht weit genug gelesen.

Aber ich habe es jetzt wieder rausgeholt

und jetzt lege ich es mir

unter das Kopfkissen und werde das

per Diffusion aufnehmen.

So habe ich die Matura geschafft

mit dem Mathematikbuch unter dem Kopfkissen.

Funktioniert.

Ja, ich finde, wir müssen noch ein bisschen

darüber reden, wie man das so in Python

dann machen kann noch und wie man das

Typing-Modul vielleicht noch so ein bisschen benutzt.

Wir hatten jetzt ein Newtype, was

irgendwie ganz cool ist. Wir hatten die Generics.

Ja, also Generics, achso, genau.

Wo wir dann schon mal, da habe ich nämlich jetzt heute

alles gehabt, als ich versucht,

da dachte ich mir so,

oh mein Gott, wenn, hoffentlich fragt das keiner, deswegen frage ich

das jetzt mal, kann mir

einer vielleicht erklären, was der Unterschied zwischen

Co-Variant, Kontra-Variant und In-Variant

und so ist, weil das kann man nämlich auch mit angeben

und ich dachte mir so, okay, ich kann es ja angeben,

aber was bedeutet das eigentlich?

Und was macht dann Bound und so?

Ich kann es aus einer

Typtheorie sagen, was Co- und Contra-Variant ist.

Ich weiß aber nicht, ob das so auf Python

auch zutrifft.

Aber ich versuche es jetzt mal so

zu erklären. Co-Variant ist,

wenn du

Schnell die Petit fragen.

Nein, es ist

irrsinnig schwierig zu erklären. Lass mich kurz

mein zweites Buch aufmachen, weil da wäre Zeichnung.

Ja.

Also bevor ich jetzt allgemeine Beschreibungen erkläre, sage ich es lieber einmal so.

In einer Kovariantenbeziehung hast du zum Beispiel einen Typ, der ist String oder Number.

Was bedeutet, dass wenn du einen Wert hast, der Number ist, dann kannst du dir auf jeden Fall auf diesen einen Typen zuweisen, der String oder Number sein kann.

Das heißt, je enger dieser Wertebereich wird, hat keinen Effekt drauf, kannst du weiterhin darauf zuweisen.

Der Kontravariant ist genau umgekehrt. Du kannst zum Beispiel jetzt nicht eine Funktion, die als ersten Parameter String oder Number oder einen Funktionstypen, der als ersten Parameter String oder Number erwartet, kannst du jetzt nicht eine echte Funktion zuweisen, die nur String erwartet, weil ja der Fall, dass auch eine Number als Parameter sein kann, nicht dadurch abgedeckt wird.

Das heißt, du hast der Typ zwar auch ein Subtyp, der Parametertyp ist ein Subtyp vom anderen, aber nachdem der in einer Funktion steht, sind die nicht zueinander kompatibel, sondern nur umgekehrt. Das heißt, du kannst einen Funktionstypen definieren, der als ersten Parameter eine Number angibt, was bedeutet, dass du auch Funktionen zuweisen kannst, die String oder Number erwarten, weil eben dieser eine Fall abgedeckt ist. Und das ist der Unterschied zwischen Kovarianz und Kontrovarianz.

brauchst du eigentlich nie, macht halt irgendwelche komischen Fehlermeldungen,

wenn du irgendwelche Sachen zuweisen willst, die dann

nicht so funktionieren.

Ist aber, glaube ich, in der Typtheorie

die korrekte Beschreibung.

Ist nicht kompliziert, ich möchte euch

da für die Shownotes eine Grafik zur Verfügung

stellen, die das wunderschön erklärt.

Und da suche ich mir den Link

jetzt wirklich raus aus meinem Buch, weil das habe ich genau

aus dem Grund habe ich es da rein.

Weil das sind die Sachen, die merke ich mir selber nie genau.

Das ist was man einmal nachlesen muss.

Also in welche Richtung kann man was irgendwie doch

voneinander erben, wenn ich das richtig verstehe?

Und das allgemeiner annotieren?

Generisieren.

Also ich habe es jetzt hier auch gerade,

wenn jemand anders spricht, kann ich ja googeln.

Also so wie ich das jetzt hier verstehe,

das bezieht sich direkt auf Python

hier und

Qualitätsquelle Stack Overflow

kann man ja auch verlinken.

Es wird hier so erklärt,

du hast zwei Klassen, Basisklasse

und eine abgeleitete Klasse.

Die derived.

Genau. B und D, also Basisklasse und abgeleitete Klasse. Und du hast irgendeine generische Typenliste mit irgendeinem Typen drin. Und jetzt ist die Frage, wenn du eine Liste hast, die den Typen B hat, also den Basistypen, kannst du die dann da verwenden, wo du eine Liste vom Typen D erwartest, also eine abgeleitete Klasse? Oder ist das andersrum?

Das wäre dann Co-Variant oder Kontra-Variant?

Genau, und das eine ist Co-Variant und das andere ist Contra-Variant,

weil du eben sagst, okay, wenn du

den als Generic verwendest,

dann geht die Beziehung in die eine Richtung oder

die Beziehung geht in die andere Richtung.

Und das ist natürlich schön, dass man da

zwei Worte genommen hat, die exakt gleich klingen.

Also Co-Variant ist, wenn man quasi annotiert

mit der Implementierung

und Contra-Variant ist,

wenn man mit der Basis

annotiert, ja.

Und In-Variant wäre dann, wenn man

nicht beides verwenden darf, weil

der sagt ja halt nö, das ist nicht genau das, was ich erwarte.

Ja, irgendwie so.

Für genauere Sachen muss man

PEP484 lesen, das haben wir ja sicherlich

alle schon gemacht.

Muss man gar nicht genauer drauf eingehen.

Ich packe die Grafik in die Schuhe

und dann schauen wir mal.

Schauen wir mal, ob das hilft.

Ja aber genau Ich dachte auch so man kann das ja angeben und dann dachte ich so Ich hab das noch nie verwendet Ist das irgendwie hab ich was pass ich was oder Und was macht dann Bound

Also weil das macht man ja irgendwie

auch bei den Contra Variants oder

ist das schon das?

Steht zumindest in der Types,

Pricing, Typing. Tatsächlich ist

in dem PEP 484 eine sehr schöne Erklärung

drin.

Mit Employees und Managers.

Wenn du

eine Funktion hast, die eine Liste von Employee

nimmst, kannst du

da eine Liste von Managers reingeben?

Und für manche

Funktionen kann das Ja sein, wenn du

halt sagst, okay, wir müssen Gehalt auszahlen, das

müssen Angestellte kriegen und wenn die Angestellten

Manager sind, dann ist es halt

so. Kann aber

auch Nein sein, dass du

zum Beispiel

keine Ahnung, alle

Angestellten aufsetzt,

die

Manager-File.

Genau.

Nee, aber dass du zum Beispiel jemanden hinzufügst

zu dieser Liste. Und wenn du sagst,

okay, die Funktion nimmt eine Liste, die

die Angestellte enthält, dann kannst du

in diese Liste auch einen Angestellten reintun.

Wenn du aber eine Liste von Managern

reingegeben hast, dann geht das nicht.

Und das

ist jetzt eben genau so eine Frage, wo du

beide Optionen haben kannst,

also so eine Situation, wo du beide haben kannst

und das

tatsächlich auch eigentlich beantworten können

musst, ob du da

eine abgeleitete oder eine Basisklasse

reingeben darfst. Eine Q-Variante

oder eine Contra-Variante. Und der Bound ist dann

quasi tatsächlich die,

wenn dann erst die Manager-Revival, weil das die

spezialisiertere Variante ist.

Ja, wir haben noch mehr von dem

Typing-Modul, damit wir uns noch mehr schöne Sachen

dazu erzählen können und mehr ergänzen können mit

präzisem Fachwissen. Und zwar den

Type-Adias und die Type-Ware,

die da noch irgendwie dazu können.

Also was ist denn der Unterschied? Und man kann ja auch noch

das schöne Keyword Type dazu schreiben

und sowas.

Ich meine, bei Type Alias, das kannst du auch

einfach so hinschreiben, es ist nur eine explizitere

Darstellung und manchmal ist es halt problematisch,

wenn du zum Beispiel einfach einen String verwendest, den du ja auch

quasi benutzen kannst, statt

und manchmal muss man das ja auch

um zyklische Imports zu vermeiden und so,

dann ist halt unklar, was gemeint ist, wenn man

nicht Type Alias davor schreibt.

Also beispielsweise, wenn ich jetzt irgendwie eine Union habe,

das kann jetzt mehrere Sachen sein, dann kann ich dann

Type Alias für verwenden, dass das damit

gemeint ist, in dem einen Namen geht. Ja, aber du könntest ja auch einfach

hinschreiben, myUnion gleich

und dann irgendwie

der Typ, Pipe-Symbol,

der andere.

Das ist dann ein Type-Alias schon.

Das selber kann ich annotieren mit, nein, ist es nicht?

Ja, also du könntest damit dann wieder annotieren.

Aber wenn du jetzt zum Beispiel

da Strings verwenden wollen würdest

für die Typen,

dann geht es halt nicht mehr so richtig.

Und dann macht,

also Type-Alias macht das dann halt explizit,

dass das halt sozusagen...

Und die Type war,

das hatten wir eben, TVK, TKV,

warum TKV jetzt da

im besonderen Sinne, weil ich diese kurzen Dinge,

einer der Gründe, warum ich Go nicht leiten kann, sind diese

einen Charakter

Variablen haben, aber ja.

Ja, das sind halt die Generics, oder, die wir vorhin hatten.

Stefan, du hast angesetzt.

Erklär uns, was Type war.

Also ich habe jetzt ganz kurz diesen

Pep4 aufgemacht und der ist

wunderschön.

Der ist super, oder?

Also Type-Variable, also ich sage immer Type-Parameter

dazu, aber das ist im Grunde genau das Gleiche.

Das ist eben diese,

ein Typ, der später durch einen

konkreten Typ ersetzt wird. Das heißt, du kannst jetzt sagen,

du hast diese Typvariable in diesem Beispiel

von pep484 ist das st,

seist type wird

das heißen dort, weil da geht es um seist,

wo du sagst,

hey, du machst jetzt eine Funktion, die

erlaubt

x beliebige Typen,

allerdings kannst du sie

durch irgendeinen Bound,

das ist das zweite dort,

der zweite Parameter,

einschränken. Also ein Bound sagt dir

oder der generelle Typ-Rameter sagt dir, alle möglichen Werte, aber später

nur ein konkreter. Und der Bound sagt dir,

alle möglichen Werte, die auch diese Eigenschaften erfüllen, später ein

konkreter. Und das ist dort in diesem Beispiel recht gut, weil du jetzt seist als Bound

definiert, was bedeutet, dass du

eine Länge definieren

können musst oder Länge lesen

können musst.

In Python hast du nur

diese Hilfsfunktion, du hast ja selten

Methoden auf Klassen, soweit ich das

weiß.

Deswegen brauchst du halt

überall diese Bounds. Andererseits

könntest du ja sagen, du hast irgendeine

Subklasse oder so.

Aber Bound ist auch etwas,

das kennen wir in anderen Programmiersprachen auch,

in TypeScript wird das als

Konstrant bezeichnet. Aber im Grund geht es darum, dass du

einfach vordefinierst, du hast ein paar Eigenschaften,

die du sicherstellen willst.

In dem Fall, was dort beim PEP484 ist,

mit diesem Upper Bound, sagst du einfach,

du willst die Möglichkeit haben, eine Länge zu berechnen.

Du willst einfach wissen, da gibt es eine Size,

das hat eine gewisse L was auch immer Spannend w es ob ich dort einen String reingeben kann weil man kann ja die L von einem String definieren Ja kannst du Alles was Lend von irgendwas hat

ist size. Also ich kenne kein

Python, aber ich habe diesen Code jetzt gelesen und weiß

sofort, was ich da zu erwarten habe,

weil ein String muss auch

eine Länge rauskriegen.

Schon cool.

Und das ist

auch sehr interessant hier, weil also diese

Type Variable, die gerade in diesem Beispiel,

ich habe es zufällig auch gerade offen,

benutzt wird.

Die wird in dieser Funktion, da wird eine Funktion definiert,

die heißt longer und die nimmt zwei Variablen

x und y und die sind beide vom Typ st

und der Rückgabewert ist

ebenfalls st.

Und das ist eine sehr interessante Sache, weil das eben

bedeutet, du kannst hier

zwei Sachen reingeben, die von

der gleichen Sorte sind und kriegst wieder eins raus,

was wieder von der gleichen Sorte ist.

Aber wir sagen gar nicht genau, was das für

eine Sorte ist, sondern wir sagen nur, das muss

als Anforderung haben,

das Minimum, was es erfüllen muss,

das ist der Bound, ich muss davon die Länge

abrufen können.

Und das hat diese Funktion

schon sehr genau spezifiziert.

Die Spezifikation dieser Funktion,

also longer x, y, ist ja

erst mal sehr lose.

Und jetzt durch diese Typvariablen und durch den

Bound ist es doch relativ genau spezifiziert

und auch sehr exakt,

würde ich sagen.

Was ich sehr spannend finde an dem Beispiel, und das ist

wahrscheinlich jetzt so ein Python-Eigenwort,

aber im ersten Aufruf wird dort dieser generische Typ-Parameter oder diese Type-Ware ersetzt durch eine List.

Das ist, glaube ich, die eckigen Klammern.

Im zweiten Aufruf, da hast du geschwungene Klammern, wird es durch ein Set ersetzt.

Also der Typ wird durch ein Set ersetzt.

Aber im dritten, da ist im ersten Aufruf eckige Klammern, im zweiten Parameter sind geschwungene Klammern.

Da wird der Parent-Type davon eine Collection verwendet, wo du sagst,

hey, okay, ist eine List, ist eine Set, also es könnte beides sein.

du nimmst einfach was, was

beide beschreibt. Finde ich cool,

dass das das Typsystem so macht. Normalerweise würde

TypeScript dir da vielleicht einen Fehler

werfen. TypeScript würde da sagen, hey,

wenn du das einmal

durch einen Typ ersetzt, dann musst du auch im zweiten

Parameter den gleichen Typ verwenden und so

findest du aber in der Hierarchie tatsächlich

einen Parent-Type, den du

nutzen kannst. Das ist ziemlich geil.

Also, richtig

cool. Ja, das ist ziemlich schön.

Also,

nämlich auch so, dass ich das jetzt verwenden möchte.

Muss ich ganz ehrlich sagen.

Ich glaube, ihr habt es so weit.

Sehr gut.

Viele Programmiersprachen-Features

werden ja durch Knight umgesetzt.

Das ist bei Python

auch nicht anders. Viele Sachen sind einfach

aus Knight durch andere Sprachen entstanden.

Den größten Knight habe ich ja durch

die Import-Signatur. Das macht einfach

so viel einfacher.

In JavaScript ist es umgekehrt. Du importierst

zuerst die Einzelelemente

aus dem Paket.

Und das ist reine Ästhetik. So ist viel

klarer. Du spezifisierst zuerst

das Paket und dann importierst du die Sachen draus.

Jeder Editor freut sich, wenn er das so kriegen kann.

Ja.

Was mich noch

interessieren würde hier an der Stelle ist

diese Overloads, die da mit drinstehen.

Das ist ja auch so eine Sache, die man nur

bei den Type Annotations findet oder

auch woanders, wo halt derselbe Methodenname

mehrfach hintereinander definiert wird.

Was macht denn das genau?

Schreibst du in

Python dort dann beide Methoden

aus? Also implementierst du da beide Methoden?

Ah, in Python musst du dich da anstrengen dafür.

Oder sind das nur die Signaturen?

In Python musst du dich da anstrengen

dafür. Das hat ja nicht mal viel mit

ja, es hat vielleicht schon was mit Hypes

zu tun, aber

also so richtiges Overloading

gibt es ja gar nicht in Python.

Du fügst eine weitere Signatur hinzu

zur Methode. Ja genau, was macht denn das?

Warum macht man denn das? Du hast noch nicht zwei Funktionen,

du hast zwei Signaturen.

Du hast eine Funktion, die

Also es ist so, der ganz grundlegende Prozess ist, dass eine Funktion in Python eine Variable ist, die halt ein Funktionssubjekt enthält. Und diese Variable hat einen Namen und diesen Namen, der ist eindeutig, den kannst du nur einmal geben. Und zu diesem Namen kannst du auch nur diese eine Funktion geben.

Was du jetzt aber machst, um Überladung zu machen und das, ich erkläre es gleich noch für die Zuhörer, ist, dass du sagst, du definierst eine Basismethode und der fügst du dann eine weitere Signatur hinzu. Und wenn diese, da ist dann eben so ein, durch Dekoratoren hast du so einen Mechanismus, der diese Signaturen entsprechend überprüft.

So, was ist Überladung überhaupt und was erreicht man damit?

Überladung ist, wenn du eine Funktion, also ganz klassisch aus dem Java-Umfeld,

wenn du eine Funktion hast, die heißt add und die definierst du für float und float

und dann kommt hinterher wieder ein float raus.

Dann funktioniert die ganz einwandfrei für floats, aber du kannst damit nicht int adden.

Du kannst keine Integer addieren, weil der Compiler dir sagt,

ich habe die Funktion gefunden, aber die geht nur für floats.

Was du jetzt in Java machst, ist, du schreibst eine zweite Funktion,

die auch Add heißt, aber die eine andere Signatur hat.

Und die wird durch das Kompilat

zu einer anderen Funktion.

Das heißt, zum Zeitpunkt des Kompilierens

kann der Compiler sagen, ah, du meintest

diese Funktion mit der Signatur oder

du meintest diese Funktion mit der Signatur.

Und das geht auch in

TypeScript, wenn ich mich recht erinnere,

dass du überladene

Methoden hast, die dann eben durch den

Compiler zum Zeitpunkt des Compilerns

die richtige

Zuweisung bekommen. Die sind dann im JavaScript-Kompilat

heißen die dann unterschiedlich, weil

die eben da unterschiedlich sind.

Das ist genau der Unterschied.

Ein Overload in TypeScript ist im Grund nur eine andere Funktionssignatur über der tatsächlichen.

Du musst mindestens zwei angeben.

Eine, die dem Typsystem mitgeteilt wird als Nutzungssignatur

und eine, die du verwenden kannst, um tatsächlich die Funktion zu implementieren.

Und dann kannst du so viele Overload schreiben, wie du willst.

und du hast dort einfach unterschiedliche

Aufrufe, durch die du

durchgehen kannst, aber im Endeffekt wird

nur eine Methode aufgerufen

oder eine Funktion aufgerufen.

Deswegen habe ich genauso nachgefragt,

weil ich bin mir nicht sicher, wie das jetzt in Python funktioniert,

weil es ist spannend.

Es ist

so Führungslieder.

In Python ist es ein bisschen anders.

In Python musst du das eben über Dekoratoren

machen, weil du diesen Namen nicht mehrfach

haben darfst und was

da im Wesentlichen passiert ist, du sagst,

wenn die Methode aufgerufen wird mit zwei Variablen

oder mit Argumenten, die diese Signatur entsprechen,

dann rufe bitte diese Subsignatur auf.

Also du fügst da quasi eine weitere Funktion hinzu,

die nur in bestimmten Fällen aufgerufen wird.

Aber das ist was, was zur Laufzeit passiert.

Also zur Laufzeit wird dann entschieden,

welche Submethode aufgerufen wird.

Das ist im Wesentlichen ein Match Case,

der da vorsteht.

Ich weiß nicht, ob das im Typing-Zusammenhang nicht was anderes ist.

Also ich meine, es gibt diese Overload-

Geschichten vielleicht in Klassen,

aber ich meine hier auch bei den

bei Funktionen, wenn ich jetzt

einfach das sozusagen für diese Typ-Annotation

verwenden will, dann ist es, soweit ich sehen kann,

auch so. Es gibt die Funktion einmal,

aber ich kann halt viele

sozusagen mit Overload

dekorierten Funktionen

haben, die keine Implementation haben,

aber wo ich sozusagen nur

quasi die unterschiedlichen

möglichen Arten, wie ich das

wie das aufrufen werden kann, halt

annotiere, weil ich das nicht in eine Annotation schreiben kann,

weil geht halt nicht.

Und ja.

Achso, okay. Da gibt's

zwei, also es gibt da, dann hab ich, also es gibt

mehrere Overload-Dinge,

denke ich. Genau, also das

das ist blöd, ja.

Es ist blöd, dass diese Sachen in

unterschiedlichen Sprachen unterschiedliche Dinge bedeuten.

Es ist, also

wenn ich der Kaiser wäre, dann wäre das anders.

Also das ist tatsächlich was, was ich vermisst habe

an Python. Als ich zu Python gekommen bin,

aus Java. In Java kannst du sagen, ich habe hier

eine Funktion, die heißt add und die nimmt Integer

und ich habe eine Funktion add, die nimmt Strings

und ich habe eine Funktion add, die nimmt, was weiß ich,

Listen. Und die machen

sehr unterschiedliche Dinge, aber im Endeffekt

das gleiche Semantische. Die fügen die aneinander.

Und die heißen gleich,

weil die das gleiche machen. Und sowas

gibt es in Python nicht, weil in Python musst du

jedes Mal einen neuen

Namen haben dafür oder einen neuen Scope

oder so. Dafür gibt es

Single Dispatch.

Ja, das hat

damit zu tun, dass

in Java überhaupt möglich ist, dass du

den gleichen Namen mehrmals vergeben kannst.

Ja, weil die beim

Kompilieren die Namen, weil die Namen weg sind

beim Kompilieren.

Nein, weil die

Funktionssignaltypen haben.

Nein, weil die Funktionssignaltypen haben.

weil Java die Typen

erfordert

und dadurch

ist einfach genug Unterschied da, um das

zu identifizieren können.

Genau, es sind unterschiedliche Funktionen. Also die Funktion

addIntInt ist eine andere Funktion

als die Funktion addFloatFloat.

Und darum ist natürlich ein JavaScript

und Python

halt

komplett anders, weil im Endeffekt

hast du halt nur eine Funktion mit ein paar Parametern

und die Typen sind ja, wie wir mitbekommen

haben, eigentlich wurscht.

Die sind dann weg.

Ja, zur Laufzeit auf jeden Fall.

Aber diesen Mechanismus, den kriegst du hin,

der heißt Single Dispatch.

From Functools import Single Dispatch.

PEP 443.

Das, was ihr beschrieben habt,

das heißt Overload,

das ist ja was ganz anderes. Python Lang Util.

Äh.

Okay.

Ich hab's jetzt hier aus From Typing.

Also, so wie ich das

gesehen hab, es gibt auch ein sehr schönes Beispiel

dafür, das ist auch aus dem Fluent Python

Buch, habe ich das da,

also das ist halt so ein Beispiel

für Methoden, die halt eigentlich

in, also die hat auch so ein Problem,

dass man mit Type halt so hat beschreiben n dass man dass halt die Typ nicht so also die ist ja auch eine Sprache ist halt eine andere Art das hinzuschreiben

Und die ist halt nicht so expressiv wie Python selber.

Das heißt, wenn ich jetzt Funktionen habe,

wie zum Beispiel min und max,

jetzt weiß ich gar nicht,

ob es das in der JavaScript-Welt auch so gibt,

aber die kann ich halt sehr schön in Python hinschreiben,

so in irgendwie so 20 Zeilen oder sowas.

Und ist sehr schön zu lesen,

ist nicht kompliziert

und die Typ-Annotation dafür

ist aber sehr, sehr schwer, weil das

halt so super generisch ist und dann kann man noch ein

Callback übergeben, das halt

irgendwie zum Sortieren verwendet wird

und sowas und

ja, die korrekten

Type-Annotationen für Min und Max sind

halt sehr viel länger als die Implementation

und das ist halt,

liegt halt daran, dass man das

in dieser neuen Annotationssprache

halt nicht so gut hinschreiben kann

und dafür, also da hast du dann halt so irgendwie

ich weiß nicht, zig Overloads, weil

du kannst das sowieso immer nur

quasi für einen Teil

der, wie man das aufrufen kann, halt

annotieren und dann musst du das halt

zehn Dinger übereinander häufen,

um das halt irgendwie

abgebildet zu kriegen und

ja, und auch in diesen Dingern sind dann halt,

waren halt lange Fehler

drin und die sind halt auch echt

schwer zu finden, also ja.

Und die machen ja auch überhaupt

gar nichts, diese Fehler, jetzt mal ganz ehrlich.

Ja gut, na gut, also

Also irgendjemand hat dann halt...

Sie haben ja oft mal lange genug was gemacht,

was sie keinen gefunden hat.

Es kann ja sein, du rufst das halt auf,

lässt es auf eine bestimmte Art

und dann läuft dein Type-Checker drüber

und der sagt, der spuckt dir dann halt

irgendeine Fehlermeldung aus,

die vollkommen unverständlich ist

und das verdirbt dir halt den Vormittag oder so,

weil du verstehst gar nicht, wo das Problem ist.

Und dann war es halt nicht mal wirklich ein Problem,

sondern es ist einfach nur etwas,

was halt in den Annotationen kaputt war

und du hast es korrekt aufgerufen.

Das ist ja schon ärgerlich.

Also ich meine, ja, also...

Ja, gut.

Zugegeben, ja.

Aber was war jetzt die Lösung, Jochen?

Ich habe dich jetzt unterbrochen, aber gibt es da jetzt eine Lösung dafür?

Kann ich jetzt da Overload sagen?

Genau, und du kannst jetzt sozusagen, wenn du eine Funktion annotieren möchtest,

aber die Annotation nicht einfach so hinschreiben kannst,

dann kannst du die möglichen Arten, wie das halt,

also wenn du mehrere Annotationen hinschreiben musst für die Funktion,

kannst du das per Overload hinschreiben.

hast dann halt der Methoden-Body

oder Funktions-Body ist

einfach Ellipsis, also Punkt, Punkt, Punkt.

Und

genau, dann kannst du halt alle Arten, wie man

das Ding halt getypt aufrufen kann,

halt hinschreiben.

So richtig schön sieht das aber auch nicht aus.

Nee, das sieht nicht schön aus.

Ausgedehnt.

Ich würde es zum Beispiel in TypeScript

auch nicht immer verwenden.

Meistens ist es ein Codespell, wenn du

Methoden oder Funktionen hast,

die mehr können soll,

als für das, was sie

beschreibt. Ja, so ein bisschen so eine Krücke,

warum machen wir das denn nicht?

Vielleicht, wenn man so ein Public-API-Interface hat,

was unbedingt benutzt bleiben muss, aus irgendwelchen Gründen.

Vielleicht für Legacy

oder sowas. Ja, also in JavaScript gibt es es, weil

also in TypeScript gibt es es,

weil du halt in JavaScript

Parameter weglassen kannst

oder

oder

Parameter an unterschiedlichen Positionen

auch was anderes heißen.

Und da der TypeScript irgendeine Methode

braucht, um das darzustellen.

Und deswegen haben wir es.

Ja, gut, wenn man Sternchen, Komma, Quark

schreibt oder sowas. Also gerade dieses

Ad-Beispiel von Johannes, das würde ich

eigentlich jetzt den TypeScript mit

Generics umsetzen.

Ja, gut.

Wenn du jetzt

die Methode Add

für Integer und die Methode Add für String hast,

musst du ja schon zwei unterschiedliche

Implementierungen haben auch.

Also an irgendeiner Stelle musst du ja deine Implementierung

verzweigen.

Nicht in JavaScript.

Ja, wenn du Plus verwendest,

okay, aber dann musst du das Plus irgendwo hin verzweigen,

weil das macht ja sehr unterschiedliche Dinge.

Ja.

Dann kann ich das dann netto überschreiben.

Ja, ja.

Ja.

Was mir noch

fehlt, wir haben schon relativ viel gesagt,

aber es ist sowas wie, ich glaube es ist eben schon

einmal gefallen, sowas wie rekursive Types oder sowas,

Wenn ich zum Beispiel einen JSON-Type definiere.

Oh, sag doch nicht sowas.

Kapitel 7.

Du bist ja noch weit entfernt von Kapitel 7.

Ja, also rekursive Types ist schon nötig.

Wenn du jetzt zum Beispiel irgendwie eine Liste definieren willst,

eine einfach verkettete Liste,

dann hast du dort nur einen Knoten

und du verweist auf den nächsten Knoten.

Aber das ist eigentlich nur ein Typsystem

für 100. Also du musst halt irgendwie

die Möglichkeit haben, dass du Typen

definieren kannst die sich selbst referenzieren k wenn n Also wie JSON oder sowas zum Beispiel tats Zum Beispiel ja genau Also in JSON kann es ja auch sein dass du

naja,

schwierig.

Ja, eine Liste von Objekten habe, in denen andere Listen stecken,

die wieder irgendwie Toys haben oder so.

Ja, genau. Oder in Array von Arrays.

Ja.

Wenn du dabei bist, ne.

Ich habe mal mit jemandem

vom TypeScript-Team gesprochen, bezüglich

rekursiven Typen.

das ist meistens ein Implementierungsdatei,

wie tief der Compiler dort

gehen kann. Also was sind die,

wie ist

der Compiler entwickelt,

dass er bald genug sagen kann,

hey, da stopp ich jetzt und passe nicht mehr weiter. Also wie

geht der Compiler mit der Regression?

Typsysteme können das eigentlich.

Hat er auch in der IDE irgendwie, ich weiß nicht,

bei JSON-Type oder sowas, bis wie viel Level

tief darf der denn gucken,

ob das noch stimmt?

Genau.

Und da werden sie auch immer besser.

der Mathematik egal.

Das ist der Mathematik egal, die guckt.

Ja, genau.

Ja, das kommt dann wieder

darauf an, welche Art von Mathematik, wenn man

den konstruktiven Zweig

anhängt. Das gibt es gar nicht.

Jason, das ist so schwierig.

Wenn du schon in der Grundvorlesung,

also ich habe ja

eine mathematische Ausbildung genossen an der

Universität, da werden dann die

natürlichen Zahlen nochmal definiert und die werden rekursiv

definiert. Da gibt es eigentlich nur eine natürliche Zahl,

das ist die 0 oder die 1, je nachdem, wo du anfangen willst.

Und dann

sagt man einfach, jede Zahl hat einen Nachfolger

und zack, hast du alle natürlichen Zahlen

beisammen. Also es geht

schon weit rein mit der Rekursion und

die geht auch weit genug in der

Mathematik.

Ja.

Ja, ich weiß nicht, haben wir noch,

ah, was mir noch einfällt, genau.

Das schließt so ein bisschen an das

Pidentik-Thema von eben an.

Ich meine, das ist ja jetzt etwas, die Typen werden ja zur Laufzeit ignoriert in Python, aber nicht immer und man müsste es auch nicht, weil im Grunde kann man rausfinden, wie die Annotationen sind und es gibt halt auch Software, die das macht, wie zum Beispiel Pydentic.

Ja, oder MyPy.

Oder FastAPI.

Ja, genau.

Gibt es sowas eigentlich in TypeScript auch?

Weil ich meine, gut,

das wird ja kompiliert zu JavaScript, aber es gibt ja jetzt auch

glaube ich Interpreter,

die direkt TypeScript interpretieren, so Deno

oder sowas macht das glaube ich, ich weiß nicht so genau.

Könnte das ja im Grunde dann tun.

Das ist ja

ein weitverbreiteter, ich glaube,

dass Deno direkt TypeScript interpretiert.

Deno hat nur einen TypeScript-Compiler

inkludiert, also kompiliert TypeScript

bevor er das JavaScript ausführt.

Also tatsächlich,

wie, also ich sage mal, im JavaScript-Bereich

reden wir eher von unterschiedlichen

Typsystemen, die existieren.

Wie Flowtype ist zum Beispiel

eins, das sehr, sehr optisch sehr, sehr ähnlich

ist zu dem, was TypeScript

zur Verfügung stellt, aber halt

in den Nansen unterschiedlich ist.

Oder eben TypeScript

und das sind auch schon die populärsten.

Der Clojure-Compiler hat einmal ähnlich funktioniert.

Wie Typs definiert werden.

Ja, CoffeeScript gab es früher.

Ja, CoffeeScript ist aber sogar eine eigene Programmiersprache.

Also wie Typs definiert werden,

das meinen.

Gleiche Historie.

Ähnlich, ähnlich.

Da gibt es auch einen wichtigen

Punkt, weil wie Typen definiert werden

in JavaScript, das ist ja eigentlich nicht

dem TypeScript

Team zu verdanken, sondern

dem ECMAScript 4 Standard, der schon

viel, viel älter ist,

der nie umgesetzt wurde, an den

sich aber alle Typsysteme jetzt irgendwie dranhalten

bei der Definition des eigenen Typsystems.

Ich würde eher sogar sagen, dass

Action-Skript, also die Flash-Programmiersprache

noch eher

ähnlicher oder verwandter mit

TypeScript und Flow-Type ist.

Aber

das ist es dann auch. Also du

hast entweder unterschiedliche Typsysteme,

dann entscheidest du dich in den meisten Fällen

heutzutage eh für TypeScript und dann

bietet dir TypeScript eigentlich alles, was du dafür

brauchst. Also du

laufst dir gar nicht in Gefahr, dass du

irgendwie

ein anderes Werkzeug nimmst.

Und TypeScript versteht halt auch komplett JavaScript. Das heißt, du kannst halt dort noch mit JavaScript-Code anfangen und dich nur einmal auf die Typ-Inferenz vom TypeScript-Type-Checker verlassen, dass du sagst, hey, ich weiß jetzt, welche Typen du verwendest, rein in der Verwendung deines Codes.

Dass du jetzt so eine retroaktive Typ-Annotation machst, macht man eher nicht. Es gibt ein paar Werkzeuge, ich könnte aber jetzt nicht den Namen dazu sagen, macht man aber aus dem Grund nicht, weil der TypeScape TypeChecker eh gut genug ist, dass er schon sehr, sehr viel herausfindet, bevor du überhaupt irgendeine Annotation machen musst.

was

ein gutes Migrations-Solid ist

ist JS das ist halt ein Typ im Kommentar wo du einfach sagst hey du hast diese Funktion die hat drei Parameter du definierst den Typen im Kommentar

und nicht im Code.

Und das machen viele Bibliotheken,

das machen sehr viele alte JavaScript-Bibliotheken,

wie zum Beispiel Lodesh oder Underscore schon.

Und TypeScript kann mit dem umgehen.

Also TypeScript kann auch Typ-Informationen aus diesen Kommentaren lesen

und hat halt so weit mehr Kompatibilität mit dem gesamten Ökosystem,

als wenn sie darauf bestehen würden, dass sie nur die Typen verwenden, die du annotierst.

Okay, aber so ein richtiges Äquivalent zu dem, was der Jochen gefragt oder gesagt hat,

gibt es nicht wirklich.

Zur Laufzeit hast du nicht wirklich mehr die Typinformation.

Also zur Laufzeit, es gibt Bibliotheken, die fügen Typinformation zur Laufzeit hinzu und leiten dadurch TypeScript-Typen ab. Aber das ist es dann schon. Es gibt auch ein paar Reflection-Geschichten.

Also okay, dass du so rumgehst.

Das ist aber alles Mumpitz. Das möchte ich nicht einmal erwähnen, weil es einfach Schwachsinn ist. Eine Sache, die aber gut ist, zum Beispiel dieses SOD, wenn du jetzt sagst, du brauchst jetzt Typinformationen zu Laufzeit auch, dann kannst du über die SOD-Bibliothek dir deinen Typen in JavaScript definieren.

Das ist aber nicht TypeScript, das ist JavaScript. Und kannst dann, wenn du diesen Typen weiter im TypeScript-Code verwenden willst, sagen, hey, leite mir jetzt aus diesem JavaScript-Konstrukt, das ich gebaut habe, das einen Typen darstellen soll, leite mir von diesem JavaScript-Konstrukt doch einen TypeScript-Typen ab, den ich weiterverwende.

und du bekommst dann zum einen einen Typ,

klassischer TypeScript-Typ,

den du in deinen Methodensignaturen verwenden kannst,

den du annotieren kannst,

wo du Typechecken hast,

das funktioniert, das ist grandios gut.

Parallel dazu hast du immer noch dieses JavaScript-Konstrukt

mit der ersten Validierung empfangen kannst.

Das heißt, du kannst sagen,

hey, du kriegst jetzt ein Chasen von einem Backend,

steckst es in den Validator rein

und kriegst entweder Ergebnisse,

die es nachher dem Typen entspricht, super,

oder Fehlermeldungen, mit denen du umgehen kannst.

und das ist eine grandiose Bibliothek.

Erstens ist sie so nah an TypeScript,

dass du wirklich sämtliche Dinge,

die du in TypeScript schreiben kannst,

auch damit umsetzen kannst.

Und zweitens ist sie schnell,

sie macht robusteren Code.

Ich bin total glücklich mit der,

die kann ich sehr, sehr gut empfehlen.

Also unbedingt.

Aber prinzipiell gilt es.

Okay, cool.

Also ein ähnliches Verfahren.

Sehr ähnlich.

In SORT ist es aber so,

dass du die Typen dann anfängst zu schreiben

in dieser JavaScript-Welt

mit den dort vorhandenen Methoden und Funktionen.

Und das ist halt umgekehrt zu dem,

was du normalerweise in TypeScript hast,

dass du sagst, du schreibst deine Typen

und die sind nach dem Kompilator einfach weg.

Also TypeScript ist so eine Erased-to-JavaScript-Sprache,

was auch bedeutet, wenn du die zur Laufzeit haben willst,

musst du in JavaScript anfangen

und musst halt dem anderen weggehen.

Ja, okay, aber da steht ja nicht,

würde ja nicht prinzipiell was dagegen sprechen, oder?

Dass du von TypeScript-Typen zu JavaScript-Typen gehst.

ist nur jetzt halt das Tooling, das

existiert nicht. Ja, okay, aber das war cool.

Also du hast auf jeden Fall das Gleiche. Unbedingt zu empfehlen.

Ja, unbedingt

zu empfehlen. Also das ist richtig, richtig cool.

Finde ich super spannend. Könnte auch für mich nützlich sein.

Also gerade wenn du

mit Backends arbeiten musst,

denen du nicht trauen kannst, herrlich.

Ja, oder mit

Inputs von Benutzern. Ich meine,

da musst du eh immer Validierung machen, aber das

kann einem ja

in dem Sinne die Arbeit ein bisschen abnehmen.

Naja, also man definiert halt, wie man gerne hätte,

dass die eigene Datenstruktur aussieht

und benutzt dann diese Information halt auch zur Validierung dagegen.

Das ist natürlich, also ja,

das ist genau eigentlich der Use Case von Pydentic auch.

Ja, ja.

Muss man das Pydentic noch genau anschauen.

Also das hört sich zum Zeitmehr,

ich habe es heute gehört, wie wir begonnen haben.

Und jetzt wieder.

Erklär mal, Jochen,

erzähl mal den Unterschied zwischen FastAPI und Pydentic.

Ach ja, FastAPI ist sozusagen ein ...

Ein Repetaface fast.

Ja, genau.

Automatisierung bereitgestellt.

Und Pidentic?

Pidentic ist eine Bibliothek, die benutzt wird von FastAPI.

Und die halt sozusagen ermöglicht, wenn man halt mit Typannotationen sozusagen oder der Syntax ...

Es gibt noch mehr, weil man kann halt auch noch mehr machen als nur die Sachen, die mit Annotationen möglich sind.

Man kann halt auch Validierungsfunktionen haben und Upper Limits und Lower Limits und weiß ich nicht, ganz viel kompliziertes Zeugs halt auch mit dazu schreiben. Das geht mit den Typannotationen natürlich nicht, aber wenn man einfach nur die Typannotationen hinschreibt, dann passiert das halt auch, dass dann sozusagen man JSON nehmen kann und man hat halt eine Objektstruktur definiert mit den Typen und dann sagt man halt, hier ist das JSON, passt das mal und validiert das mal.

Genau, und wenn es nicht, dann kriegst du 4-2-2 zurück,

weil da fehlt irgendwas.

Wenn es nicht okay ist, kriegt man halt schöne Fehlermeldungen

auch zurück, wo dann genau gesagt wird,

so an der Stelle hast du gesagt,

das soll ein Number sein, aber

da ist ein String oder

das ist halt irgendwie, das passt sonst wie nicht.

Das soll eine Liste sein, aber das ist halt nicht.

Ja, und das ist natürlich nett.

Also es ist quasi

das, woraus

FastAPI gebaut wird. FastAPI ist

identisch via

HTTP.

Ja, plus es sind noch so ein paar

Sachen zusätzlich dabei.

Starlet ist halt irgendwie sozusagen das alles, was

HTTP angeht oder so, macht

darunter, die Bibliothek von Tom Christie.

Also FastAPI ist schon so ein bisschen

ist halt so irgendwie

drei sehr coole oder drei, vier

sehr coole Open-Source-Bibliotheken in einem French-Code

irgendwie quasi. Noch so Routing

das hat man halt irgendwie von

Flass früher kannte, als Dekorator oben

an der Route dran.

Ja genau, das ist natürlich auch sehr alt.

Also Stefan, wenn du

FastAP schon kennst, dann weißt du auch

wie Pedantic funktioniert, nur halt innerhalb.

Okay.

Also wie gesagt, ich habe den Namen in

Architektur-Diagramm geschrieben, also das ist

meine Erfahrung damit, aber

reicht anscheinend.

Ist schon mehr damit gemacht als viele andere.

Genau.

Ja.

Genau, also ja, das ist auf jeden Fall

auch so noch ein ganz interessanter Ding,

weil ich meine, das ist ja tatsächlich so, wie viele Leute

das benutzen. Viele Leute benutzen dann einen TypeDict

und denken, das würde passieren, dass es validiert wird,

aber es passiert halt nicht.

Ja, genau.

Ja, ansonsten, ich weiß es nicht. Haben wir noch irgendwas

Großes vergessen oder so? Aber ich glaube,

ansonsten, ich habe hier

fast nichts mehr, was ich noch irgendwie unbedingt

gerne wissen wollte.

Ja, nach anderthalb Stunden

alles über

Typsysteme und Typen gesagt.

Das ging ja relativ schnell jetzt.

Ja.

Für meinen Typen habt ihr immer noch keine Erklärung gefunden, aber sonst.

Ja.

So Typen wie dich, Dominik,

ist schwer zu beschreiben.

Das ist so.

Ja.

So, ja.

Wirklich, ich finde es schön.

Stefan, hast du noch was, was du unbedingt loswerden

wolltest? Ich glaube, ich habe jetzt noch

ein anschauliches Beispiel gefunden zu

Co-Varianz und Kontra-Varianz, nachdem ich mir

die Grafik so lange angeschaut habe. Ich hoffe, ich kann es erklären.

Co-Varianz

ist in Wirklichkeit, was

wir als Subtyping

verstehen. Angenommen, du hast ein Lebewesen,

dann hast du ein Subtyp davon, das ist ein

Pflanzenfresser, dann hast du ein Subtyp davon, das

ist eine Kuh. Das heißt, du wirst immer konkreter und konkreter

und konkreter. Was bedeutet, wenn

du irgendwo ein Lebewesen erwartest, kannst du dort

einen Pflanzenfresser reinschmeißen, kannst aber auch Kühe

reinschmeißen oder Schafe reinschmeißen oder

Veganer.

Von mir aus, ne?

Und das ist Co-Varianz.

Das heißt, du kannst

etwas sehr Breites akzeptieren

und kannst was sehr Konkretes reinstopfen,

wenn der Subtyp...

Das heißt, ich erwarte ein Lebewesen als Type Annotation quasi.

Genau, genau, genau.

Jetzt hast du aber zum Beispiel

eine andere Co-Varianz,

nämlich du hast jetzt Pflanze und davon

abgeleitet Gras und davon

abgeleitet vielleicht Heu oder so Und jetzt willst du eine Funktion zur Verf stellen die akzeptiert Grasesser dann kannst du dort bei den Grasessern K aber auch Pflanzenfresser reinschmei

Wenn du jetzt aber sagst, du akzeptierst jetzt Pflanzen, also alle die Pflanzen oder Funktionen von Entitäten, die alle Pflanzen essen können, dann kannst du dort keine Kühe reingeben, weil Kühe können nur Gras essen.

Und das ist Kontrovarianz.

Das heißt, du hast zwar auch einen Subtypen,

du hast einen sehr breiten Typen. Ich akzeptiere

ja Pflanzenfresser. Allerdings

kannst du keine Kühe reingeben, weil Kühe nur Gras

essen dürfen.

Und Invarianz ist dann ganz festgesetzt, dass

nur den einen speziellen Typ. Genau, Invarianz ist

die beiden Richtungen.

Also ich hoffe, dass das nochmal

veranschaulicht. Ich glaube, wir gucken

lieber dein Bild nochmal an. Ich hoffe, das Bild ist so

anschaulich für die Leute,

die ausgestiegen sind.

Ja, super.

Da wir sicherlich ganz viele E-Mails kriegen und das in den

nächsten vier Folgen alles nochmal

präsentieren.

Ist ja auch okay, wenn da eine Erklärung dabei ist.

Hallo, jetzt peistenpodcast.de

Wir haben aber noch

gar nicht ganz fertig, weil wir möchten

noch unseren Pick der Woche, glaube ich,

auswählen.

Ich fange mal an.

Stefan, weißt du denn, was ein Pick ist?

Ja, also müssen wir jetzt irgendeinen Link raussuchen,

den er total grandios findet.

Ja, genau.

Irgendwas Schönes.

Meistens haben wir Python-Module, aber

ich nehme tatsächlich, ja auch nicht immer,

ich nehme tatsächlich diesmal eins

von Simon Willison und zwar das LLM.

Ich glaube, das haben wir bei einer der Machine Learning Folgen

das Kommandozeilentool.

Das war schon in Shownotes irgendwo gehabt, aber es ist tatsächlich

bei mir ist es vermehrt in Benutzung.

Im Monkey Patch schon immer das Default,

aber sonst ist es sehr, sehr schön, weil du

halt ganz viele Templates und

Chains von Templates direkt benutzen kannst

in deiner Kommandozeile, um halt

mit den verschiedenen Modellen zu sprechen,

direkt, die du da haben willst.

und es ist toll, wenn man

harte Instruktionen gibt, dann so die

Standard-Persönlichkeit des

antwortenden LLMs

irgendwie so ein bisschen gerade

zu rücken auf das, was man selber gerne als Antwort

hätte.

Such dir die Leute genug gut

aus, mit denen du sprichst, das wollte ich damit sagen

und deswegen

viel Spaß. Und dann lädst du uns ein, Dominik.

Weiterhin viel Spaß

bei den nächsten Picks, wollte ich noch sagen.

Ja.

Ja, was hast du denn geblickt, Jochen?

Was wollte ich? Ah, genau, ich dachte

mir so, naja, vielleicht auch ein Buch mal.

Und zwar eins, das ich nicht gelesen

habe. Aber wo man

das alles nachlesen kann, kann man auch

die Antworten, wenn man

drauf gekommen ist, wie das sein muss, an uns schicken.

Und zwar The Little

Typer ist ein Buch, das

ich habe es versucht zu lesen, es ist irgendwie, ich habe

dann zwischendurch aufgegeben.

Das muss ich sagen wie Experiment mit Types entbei Ja Aber da steht da steht das glaube ich alles ganz genau drin wenn man das wissen will Und vielleicht nochmal was Praktisches weil ja

das ist ja doch nicht

für alle wahrscheinlich.

Doku ist ganz nett,

auch nicht Python, sondern

Go. Geschichte,

Heroku hatte ja in letzter Zeit

so ein bisschen Probleme und

ist nicht mehr

so richtig der Platz, wo man vielleicht

so mal so, wenn man, also früher hat man das ja

irgendwie mal irgendwas mal eben

deployen wollte, hat man das oft dann bei Heroku

oder so getan, weil das halt

sehr einfach war, aber das

geht irgendwie nicht mehr.

Und das kann man auch im Selbstmodus...

Wo würdest du das jetzt machen, Jochen?

Also meine Lösung dafür ist ja, dass ich

das halt einfach, ich hab da so meine Standard

Ansible...

Ja, okay, gut. Also du

bist vom, dir ist

Heroku zu kompliziert geworden und

deshalb hast du jetzt deine eigene Hosting-Lösung

gebaut, aber das ist

natürlich keine Option, die jetzt viele

dazu haben. Genau, also das kann ich auch nicht unbedingt

empfehlen, das ist das unerwartet

kompliziert, aber

bei mir geht's jetzt daher, hab ich das Problem nicht mehr.

Und ich mach ja auch kein Docker oder so,

sondern ich deploye dann direkt

irgendwie

Knallerhart, Bare Metal. Ja, genau.

Und

bei Doku

hat man dann halt irgendwie sowas, wo man

dann so ähnlich wie mit Heroku einfach, man

hat halt so ein POC-File und dann kann man das einfach

direkt und da auch, also wenn man

einen Docker-Container bauen kann, kann man direkt Docker-Container

dahin deployen und die laufen dann unter

Subdomain direkt mit HTTPS und so.

Arbeitet das sogar mit Heroku, also Doku?

Äh, nee, nee, das ist

also, aber du musst halt das Doku

auf einem von, von, von

irgendwo auf einem, weiß ich nicht, auf einer

virtuellen Maschine, irgendeinem

Dings halt deployed haben. Achso, ein self-hosted

Heroku. Genau, self-hosted Heroku

quasi. Genau.

und genau, das ist glaube ich manchmal ganz

hilfreich, sowas zu haben.

Okay, dann

schließe ich mich da direkt mal an, weil

in dem Fall habe ich drei Picks.

Der erste

ist Vercel.

Das ist wie

Heroku nur cooler.

Der zweite wäre

Fly.io. Das ist quasi

Docker-Sachen

auf Hosted-Infrastruktur überall hin

machen und die

machen krasses technisches Zeugs damit. Also du

schickst dir den Docker-Container, aber die zerlegen

den und

bauen sich da eigene Sachen draus.

Das ist auch technologisch sehr interessant.

Das war jetzt aber

der opportunistische Pick,

nur um da die

Alternativen zu Heroku und

Self-Hosted einmal gesagt zu haben.

Hier sind wir ganz tief in den Pop-Bretchen.

Genau.

Mein eigentlicher Pick ist was ganz anderes.

Und zwar,

das ZDF hat ja eine Mediathek

und auf dieser Mediathek kann man

Sachen ansehen und wenn man ein paar Sachen angesehen hat,

dann versucht das ZDF da Recommendations

draus zu machen Wow das ist das erste Mal seit Ewigkeiten dass ich von Fernsehen etwas h Du meinst das ZDF meinst du das tats Fernsehen Ja

Das zweite

deutsche Fernsehen, meine ich.

Und die,

also nur die Mediathek.

Und weil das

ZDF ja in öffentlich-rechtlicher Hand ist,

haben die sich gesagt, eigentlich müssen wir das ja den Leuten

zurückgeben. Und das haben sie tatsächlich gemacht.

Die haben ihr Recommendation-System

auf GitHub gepackt.

Und man kann das jetzt ansehen.

GitHub ZDF minus Open Source.

Gibt es auch jetzt schon

ein Repository drunter. Das heißt

Recommendations PA Base.

Und da sind,

da ist das Recommendations System

vom ZDF drin. Und fand ich einfach spannend,

das mal anzusehen.

Weil da ja doch auch einiges

an Arbeit drin steckt. Und weil es da auch

viele Firmen gibt, die sowas gerne hätten.

Genau, das war's von mir. Stefan, hast du noch was für uns dabei?

Ich habe noch etwas herausgefunden, das ist schon ein älterer Artikel von Bob Nystrom aus dem Jahre 2015. Heißt What Color is Your Function? Und Bob Nystrom ist einer der Sprachdesigner, der jetzt aktuell an Dart arbeitet.

und das ist sehr spannend, weil er versucht zu erklären

anhand von Farben,

wie sich normale Funktionen und asynchrone Funktionen

im Sprachdesign unterscheiden.

Also rein aus der Perspektive von,

welche Herausforderungen kriegst du als Sprachdesigner,

wenn du so ein Asian-Greed-Konstrukt gestalten musst.

Und wie gesagt, der ist schon ewig alt,

aber er ist vor kurzem wieder bei uns in der Firma aufgeprobt.

kann ich sehr empfehlen.

Versuch das so zu erklären, dass du

die Ergebnisse

oder die Erkenntnisse

in Python genauso anwenden kannst.

Und

finde ich immer wieder sehr interessant.

Gehe sehr oft wieder drauf zu.

Für die

Programmiersprachen Interessierten.

Ja, sehr cool.

Also quasi diese Analogie oder diese Metapher

habe ich auch schon häufig gehört. Ich wusste aber nicht, wo sie

herkommt und ja, das muss ich auch irgendwo mal lesen.

Ne, da gibt es tatsächlich noch was Älteres.

What Color Are Your Bits?

Das ist von 2004.

Da geht es um die Herkunft von

Bits.

Also ob deine Bits

urheberrechtlich geschützt sind oder nicht.

Was du damit machen kannst,

um die Farbe, damit sie die Farbe ändern.

Aber das ist, ja. Also ich

musste da auch zuerst dran denken. Also es scheint eine gute

Metapher zu sein. Wir können das ja beides

verlinken. Ja, sehr gerne.

Ja,

ja, cool. Ich würde

sagen, herzlichen Dank, dass ihr heute alle wieder da

Aber herzlichen Dank, Stefan.

Herzlichen Dank, Johannes.

Ja, danke für die Einladung.

Freut mich sehr.

Sehr gerne.

Dann, ja, bleibt uns gewogen.

Schaltet uns wieder ein.

Hört uns, wo immer ihr gerade seid.

Morgens, mittags, nachts, abends.

Tagsüber zum Schlafen, zum Einschlafen.

Einen wunderschönen Tag.

Bis bald.

Tschüss.

Ciao.

Tschüss.