Gawain, the finest night alive (literally Þe most kydde knyȝtez vnder Krystes seluen) committed one indisputable, albeit minor, transgression under a regime of unsparing precision.
> ȝe han redily rehersed, bi resoun ful trwe,
Alle þe covenauntz þat I yow kende...
("You have readily recapitulated, by fully accurate accounting, all covenants that I declared.")
I can't think of a more fitting name except, perhaps, the speaker of these lines: the exacting Lord Bertilak.
> the finest [k]night alive (literally Þe most kydde knyȝtez vnder Krystes seluen)
Some scattered thoughts:
- As far as I can tell kyðde means "known" and is only indirectly a statement about his quality as a knight. You can be the most famous without being the best.
- Resoun ["reason"] does means 'accounting', but as in 'give an account of what happened', not in the modern sense of "financial figures". I have difficulty understanding your translation for that reason.
- I'm curious why there's a 'v' in "covenauntz" when "seluen" is spelled with a 'u', or, for that matter, when "vnder" is spelled with a 'v'.
- Tolkien (as seen on wikisource) and Richard Morris (Project Gutenberg) have And þou hatȝ redily rehersed, bi resoun ful trwe / Clanly al þe couenaunt þat I þe kynge asked. (This solves the problem of why there would be a 'v' in covenaunt...) This seems to acknowledge that Gawain has accurately repeated the terms of the single covenant that the Green Knight has declared to Arthur ("let one of your men take up my guisarme and deal me any blow, and I will return the same blow twelve months hence"), not a list of every agreement he's ever made with anyone.
- Does Lancelot exist in the source you're quoting from? The Knight of the Cart seems to predate Gawain and the Green Knight by a couple of centuries.
(While looking into some of these questions, I found the following project:
There seems to be a much bigger problem with calling Gawain "the finest knight" based on the line þe most kyd knyȝteȝ vnder Krysteȝ seluen - isn't knyȝteȝ plural?
With all þe wele of þe worlde þay woned þer samen, [With all the wealth of the world they were there together]
þe most kyd knyȝteȝ vnder krysteȝ seluen, [the best-known knights under Christ's self]
and þe louelokkest ladies þat euer lif haden, [and the loveliest ladies that ever lived] ("had life"?)
and he þe comlokest kyng þat þe court haldes [and he the comeliest king that holds the court]
Granted, I'm mostly going off of a dictionary of Middle English here, but I note that Morris' edition annotates this passage as "All was joy in hall and chamber, among brave knights and lovely ladies". And the structure of the passage, describing how "they" are all "together" at court, the knight(s) and the ladies and the king, really strongly suggests that it is in fact the knights and not the knight.
I really wish there was a "strict" mode like there is in perl.
I know thats incredibly unlikely, as python is captain duck typing, and type inference is built so deeply into the language internals that its almost impossible to undo.
But, just think of how many bugs you could squash by forcing type inference up front. (yes, it would also cause a whole load of others as well.)
Perhaps I should just use c# instead, as that basically has all of this, with the option for looseygoosey mode.
I write python code for more than 20 years and I never hit a bug that was related to a variable type. Really don’t understand all the type hint noise. To me it just makes the code harder to read
I've been writing Python since v1.4 and no other language comes close to matching my brain so well. I've rarely hit such bugs, but I hit a gigantic source of them at one job.
It was a 1-2M line codebase built in the Python 2.3-2.5 years. A pattern that had evolved in that codebase was to pass around a context dict to every non-trivial call. It was always the first parameter (other than `self`) and always had the same name. The only way to know the contents of the dict was to know the upstream call path to your function (not just the stack, any detours could have written into it as well). Things like a "price" whose value might be an integer number of US pennies or a Money object with a value and a currency identifier (e.g., USD, JPY, etc.). Much of the code just assumed it was whatever it was the first time they inspected the context dict as it arrived at their call site. Someone else modifies a code path and suddenly the contents of the context dict change on you. If your automated tests don't include that new code path, you catch the issue in prod. So, automated tests had to include all possible run-time call paths to catch these bugs before deployment, and that's impractical.
To me, one of the most important advancements Python has ever made is frozen, kw_only dataclasses with thorough type hints. They bring a lot of clarity to the code that uses them, such code is easier to test, and there are fewer bugs discovered at run-time. Extensive use of them makes type inference easier, so hints can me skipped in many places. Any difficulty in creating them often means the data model is not sufficiently flushed out, and that's good to know. I rarely write non-dataclass classes in recent years. I do add read-only properties to dataclasses liberally.
All this fixes many of the challenges that come with Python's highly dynamic nature, but let us keep many of the benefits.
That seems impossible, unless you’re using a very unusual definition of “bug related to a variable type”.
You’ve never had a bug caused by None showing up in code that didn’t expect it? Or getting an object of the wrong type that didn’t have the method you tried to call on it?
I have written for a similar amount of time, and I think I've just got used to it.
The classic is pulling in json or some other structured data and something not being the type you expect. The error happens way down the line, rather than at import, because why would you do a full validation every time you use JSON right?
I think typehinting is pretty useless in python. Its a nice idea and if your IDE is setup for it, can provide useful information that you're doing something wrong. But its requires lots of tooling and setup to provide useful signal, and is optional.
I really wish more people would take a look at the tools they used and considered "does this tool actually do what I need, or am I bending it because toolbox is limited?".
I won't go as far as to say this is awful but I will say, why? If you want or need this, please change languages. There are so many strongly typed languages out there.
This is cool. And I appreciate the cheeky comment about not using this program if your IDE or whatever does type checking already :)
But honestly, after I realized I appreciate types being enforced, I started writing in different languages. I rarely return to Python unless I'm scripting something that doesn't require longevity.
(And actually, my personal objection is incidental: The python syntax is not pretty to begin with and the situation does not improve with even more visual verbosity)
That's an interesting objection, given Python is the closest programming language to English. Understandable if your native language isn't English, but really strange otherwise IMO.
Semantic indentation is fundamentally an insane design. And I don't mean "insane" as a colloquialism for "dumb". I mean it is literally not a sane choice to make.
English would make a horrid programming language, so being close to it is not a plus.
Nearly everybody agrees that a neat formatting style is better and more readable than a messy inconsistent one. So while designing a programing language intended to be highly readable we jump two steps ahead. mandatory linting, make the neat format part of the syntax, remove the parts of the syntax now superfluous due to the mandatory neat format, and you have python.
> English would make a horrid programming language, [...]
We now have definitive proof that this is incorrect: LLMs make using English - and any other natural language - very straight-forward to instruct machines. Similar to how the compilers and interpreters make the bastardized subset of natural language that we formalize into "programming languages" translatable into machine language. Ultimately the goal is identical: human-machine communication.
Considering the endless arguments over C syntax I really don't see what is so weird about Python indentation. It has the nice effect of making code look a lot more consistent.
In the age of auto-formatters, I have less and less sympathy for this point of view.
Any widely used formatter indents along semantics anyway, so why clutter your code with curly braces everywhere if stucture is clear from indentation? Might as well make it semantic.
Before auto-formatters, there was the occasional case where you could argue that some quick hack made something more readable, at the expense of less consistency and wasted time arguing about this in code reviews. But that ship has sailed, arguably rightfully so.
And that doesn't even bring the LLM angle. If code is generated by a machine anyway and you just review it, if even that, why still bash indentation as a semantic construct?
If you have to run your source code through a formatter to make sure it doesn’t have mixed tabs and spaces that is not the flex you seem to think it is.
If you’re going to just have an LLM write all the code anyway why bother with a slow janky mess like python at all? Just make it write rust or java or go or literally anything.
Imagine having a magical machine that can write code in any programming language ever conceived, and you ask it to pick the language whose community thinks virtualenvs are a reasonable solution as opposed to a mark of profound shame. Couldn’t be me.
Python code using advanced features of the language (see for example [1]) look as much like line noise as C++ template metaprogramming. If "close to the english language" is your criterion, I believe COBOL should rank higher than python:
ADD transaction-balance TO total-balance.
Is readable to a layman whereas this isn’t:
total-balance += transaction-balance
Or even worse for someone who learned algebra but not programming (this looks like an equation, and transaction-balance is therefore equal to zero):
Yes, the more natural language-like, the better. I think the issue with BASIC, COBOL, etc is they're too English-like, because it forces everyone to learn a lot of English in order to learn programming. Mathematics uses more universal symbols, which is a better compromise. It also scales better as it's far less effort to type "+" vs "ADD", etc.
Perl is another language I would rank as much closer to English than Python is. Cobol might take the crown though, at least if we exclude joke languages
i feel like you probably just shouldn't return None, as it causes issues when tracing problems through the system.
If you must return None somewhere, I'd really prefer it to happen in one place (so the top level function may return None if something weird happens, but all the individual functions return a value).
But to be fair, this is probably just trauma from tracking down weird sentinel values.
I wish the people spearheading the charge to integrate static typing into Python had borne in mind the old aphorism about not being able to make an octopus by nailing legs to a dog.
Python is a great dynamic language. There are many great statically typed languages. Why does every great dog have to become a half-assed octopus?
May as well be strict, right! We have the technology.
Agents will fix lint issues same as any other kind of error. So lint in a blocking pre-commit hook. End result: 100% strongly typed agent written code, at least one kind of slop gone.
Gawain, the finest night alive (literally Þe most kydde knyȝtez vnder Krystes seluen) committed one indisputable, albeit minor, transgression under a regime of unsparing precision.
> ȝe han redily rehersed, bi resoun ful trwe, Alle þe covenauntz þat I yow kende...
("You have readily recapitulated, by fully accurate accounting, all covenants that I declared.")
I can't think of a more fitting name except, perhaps, the speaker of these lines: the exacting Lord Bertilak.
You're a man of culture my good sir.
> the finest [k]night alive (literally Þe most kydde knyȝtez vnder Krystes seluen)
Some scattered thoughts:
- As far as I can tell kyðde means "known" and is only indirectly a statement about his quality as a knight. You can be the most famous without being the best.
- Resoun ["reason"] does means 'accounting', but as in 'give an account of what happened', not in the modern sense of "financial figures". I have difficulty understanding your translation for that reason.
- I'm curious why there's a 'v' in "covenauntz" when "seluen" is spelled with a 'u', or, for that matter, when "vnder" is spelled with a 'v'.
- Tolkien (as seen on wikisource) and Richard Morris (Project Gutenberg) have And þou hatȝ redily rehersed, bi resoun ful trwe / Clanly al þe couenaunt þat I þe kynge asked. (This solves the problem of why there would be a 'v' in covenaunt...) This seems to acknowledge that Gawain has accurately repeated the terms of the single covenant that the Green Knight has declared to Arthur ("let one of your men take up my guisarme and deal me any blow, and I will return the same blow twelve months hence"), not a list of every agreement he's ever made with anyone.
- Does Lancelot exist in the source you're quoting from? The Knight of the Cart seems to predate Gawain and the Green Knight by a couple of centuries.
(While looking into some of these questions, I found the following project:
https://digitalcollections.ucalgary.ca/Browse/Collections/Ga...
https://wpsites.ucalgary.ca/gawain-ms/wp-content/uploads/sit...
https://wpsites.ucalgary.ca/gawain-ms/wp-content/uploads/sit...
which I'm linking here in case other people find it interesting, and also in case this makes it easier for me to find it again myself one day.)
There seems to be a much bigger problem with calling Gawain "the finest knight" based on the line þe most kyd knyȝteȝ vnder Krysteȝ seluen - isn't knyȝteȝ plural?
With all þe wele of þe worlde þay woned þer samen, [With all the wealth of the world they were there together]
þe most kyd knyȝteȝ vnder krysteȝ seluen, [the best-known knights under Christ's self]
and þe louelokkest ladies þat euer lif haden, [and the loveliest ladies that ever lived] ("had life"?)
and he þe comlokest kyng þat þe court haldes [and he the comeliest king that holds the court]
Granted, I'm mostly going off of a dictionary of Middle English here, but I note that Morris' edition annotates this passage as "All was joy in hall and chamber, among brave knights and lovely ladies". And the structure of the passage, describing how "they" are all "together" at court, the knight(s) and the ladies and the king, really strongly suggests that it is in fact the knights and not the knight.
> "You have readily recapitulated, by fully accurate accounting, all covenants that I declared."
This should be in the README.
I really wish there was a "strict" mode like there is in perl.
I know thats incredibly unlikely, as python is captain duck typing, and type inference is built so deeply into the language internals that its almost impossible to undo.
But, just think of how many bugs you could squash by forcing type inference up front. (yes, it would also cause a whole load of others as well.)
Perhaps I should just use c# instead, as that basically has all of this, with the option for looseygoosey mode.
I write python code for more than 20 years and I never hit a bug that was related to a variable type. Really don’t understand all the type hint noise. To me it just makes the code harder to read
I've been writing Python since v1.4 and no other language comes close to matching my brain so well. I've rarely hit such bugs, but I hit a gigantic source of them at one job.
It was a 1-2M line codebase built in the Python 2.3-2.5 years. A pattern that had evolved in that codebase was to pass around a context dict to every non-trivial call. It was always the first parameter (other than `self`) and always had the same name. The only way to know the contents of the dict was to know the upstream call path to your function (not just the stack, any detours could have written into it as well). Things like a "price" whose value might be an integer number of US pennies or a Money object with a value and a currency identifier (e.g., USD, JPY, etc.). Much of the code just assumed it was whatever it was the first time they inspected the context dict as it arrived at their call site. Someone else modifies a code path and suddenly the contents of the context dict change on you. If your automated tests don't include that new code path, you catch the issue in prod. So, automated tests had to include all possible run-time call paths to catch these bugs before deployment, and that's impractical.
To me, one of the most important advancements Python has ever made is frozen, kw_only dataclasses with thorough type hints. They bring a lot of clarity to the code that uses them, such code is easier to test, and there are fewer bugs discovered at run-time. Extensive use of them makes type inference easier, so hints can me skipped in many places. Any difficulty in creating them often means the data model is not sufficiently flushed out, and that's good to know. I rarely write non-dataclass classes in recent years. I do add read-only properties to dataclasses liberally.
All this fixes many of the challenges that come with Python's highly dynamic nature, but let us keep many of the benefits.
That seems impossible, unless you’re using a very unusual definition of “bug related to a variable type”.
You’ve never had a bug caused by None showing up in code that didn’t expect it? Or getting an object of the wrong type that didn’t have the method you tried to call on it?
I have written for a similar amount of time, and I think I've just got used to it.
The classic is pulling in json or some other structured data and something not being the type you expect. The error happens way down the line, rather than at import, because why would you do a full validation every time you use JSON right?
I think typehinting is pretty useless in python. Its a nice idea and if your IDE is setup for it, can provide useful information that you're doing something wrong. But its requires lots of tooling and setup to provide useful signal, and is optional.
This is awful. I love type correctness, but going all the way to flag PORT=8080? There should be a basic level of type inference.
Especially for “typed” languages that have done typing very wrong, as Python or Typescript.
I really wish more people would take a look at the tools they used and considered "does this tool actually do what I need, or am I bending it because toolbox is limited?".
I won't go as far as to say this is awful but I will say, why? If you want or need this, please change languages. There are so many strongly typed languages out there.
I agree. This looks like a dogmatic types-everywhere, unpythonesque limitation. Add type inference and I’ll buy it.
Is 8080 a number or a string? The distinction matters in certain contexts.
Can you elaborate how those languages have "done typing very wrong"?
This is cool. And I appreciate the cheeky comment about not using this program if your IDE or whatever does type checking already :)
But honestly, after I realized I appreciate types being enforced, I started writing in different languages. I rarely return to Python unless I'm scripting something that doesn't require longevity.
What languages are you using ?
Maybe not for me but I love the attitude.
(And actually, my personal objection is incidental: The python syntax is not pretty to begin with and the situation does not improve with even more visual verbosity)
> The python syntax is not pretty to begin
That's an interesting objection, given Python is the closest programming language to English. Understandable if your native language isn't English, but really strange otherwise IMO.
Semantic indentation is fundamentally an insane design. And I don't mean "insane" as a colloquialism for "dumb". I mean it is literally not a sane choice to make.
English would make a horrid programming language, so being close to it is not a plus.
I think it makes a lot of sense.
Nearly everybody agrees that a neat formatting style is better and more readable than a messy inconsistent one. So while designing a programing language intended to be highly readable we jump two steps ahead. mandatory linting, make the neat format part of the syntax, remove the parts of the syntax now superfluous due to the mandatory neat format, and you have python.
> Semantic indentation is fundamentally an insane design
That is a common complaint against Python, and tbh it also made me uneasy at first.
But honest question: Do you write any Python yourself?
I ask because I’ve only heard this objection from people who do not write Python at all.
IME, people soften up on it after some use. I find that this is the case for many (visual) aspects of syntax.
> English would make a horrid programming language, [...]
We now have definitive proof that this is incorrect: LLMs make using English - and any other natural language - very straight-forward to instruct machines. Similar to how the compilers and interpreters make the bastardized subset of natural language that we formalize into "programming languages" translatable into machine language. Ultimately the goal is identical: human-machine communication.
Considering the endless arguments over C syntax I really don't see what is so weird about Python indentation. It has the nice effect of making code look a lot more consistent.
In the age of auto-formatters, I have less and less sympathy for this point of view.
Any widely used formatter indents along semantics anyway, so why clutter your code with curly braces everywhere if stucture is clear from indentation? Might as well make it semantic.
Before auto-formatters, there was the occasional case where you could argue that some quick hack made something more readable, at the expense of less consistency and wasted time arguing about this in code reviews. But that ship has sailed, arguably rightfully so.
And that doesn't even bring the LLM angle. If code is generated by a machine anyway and you just review it, if even that, why still bash indentation as a semantic construct?
If you have to run your source code through a formatter to make sure it doesn’t have mixed tabs and spaces that is not the flex you seem to think it is.
If you’re going to just have an LLM write all the code anyway why bother with a slow janky mess like python at all? Just make it write rust or java or go or literally anything.
Imagine having a magical machine that can write code in any programming language ever conceived, and you ask it to pick the language whose community thinks virtualenvs are a reasonable solution as opposed to a mark of profound shame. Couldn’t be me.
> Just make it write rust or java or go or literally anything.
Not literally anything. Just go the full distance and have it directly output binary. No need for any intermediate code at all.
Python code using advanced features of the language (see for example [1]) look as much like line noise as C++ template metaprogramming. If "close to the english language" is your criterion, I believe COBOL should rank higher than python:
ADD transaction-balance TO total-balance.
Is readable to a layman whereas this isn’t:
total-balance += transaction-balance
Or even worse for someone who learned algebra but not programming (this looks like an equation, and transaction-balance is therefore equal to zero):
total-balance = total-balance + transaction-balance
[1] https://stackoverflow.com/questions/6760685/what-is-the-best...
Yes, the more natural language-like, the better. I think the issue with BASIC, COBOL, etc is they're too English-like, because it forces everyone to learn a lot of English in order to learn programming. Mathematics uses more universal symbols, which is a better compromise. It also scales better as it's far less effort to type "+" vs "ADD", etc.
Perl is another language I would rank as much closer to English than Python is. Cobol might take the crown though, at least if we exclude joke languages
I think similar to `dict[str, Any]`, my (justified?) recent pet peeve is `| None`.
I posted this yesterday pretty much on that: https://charemza.name/blog/posts/software/type-safety/type-s...
Yeah, that always stinks of types look nice, but I can't be bothered to try a little harder.
What do you think it should be? I use | None a lot and it doesn’t seem like a smell to me
i feel like you probably just shouldn't return None, as it causes issues when tracing problems through the system.
If you must return None somewhere, I'd really prefer it to happen in one place (so the top level function may return None if something weird happens, but all the individual functions return a value).
But to be fair, this is probably just trauma from tracking down weird sentinel values.
Ah right, I didn’t consider this was about return types! I agree that returning None is often a smell.
Asking as an outsider: what's the issue with `| None`? Is it not type checked properly? Just prefer to do all error handling with exceptions? Other?
Be cool to have a strict Python that actually runs fast with types...
Maybe mypyc? https://github.com/mypyc/mypyc
To be honest, I never tried it personally, but I try to check up on its status every couple of months.
There's also shedskin.
https://github.com/shedskin/shedskin
>a strict Python that actually runs fast with types...
Isn't that just C with extra steps
C is the last thing I'd call strict XD
I wish the people spearheading the charge to integrate static typing into Python had borne in mind the old aphorism about not being able to make an octopus by nailing legs to a dog.
Python is a great dynamic language. There are many great statically typed languages. Why does every great dog have to become a half-assed octopus?
Maybe just... Stop writing py?
How to wreck a great language
Python 9.x release notes: we are a statically typed language now.
Yes! Exactly what a long term codebase needs.
May as well be strict, right! We have the technology.
Agents will fix lint issues same as any other kind of error. So lint in a blocking pre-commit hook. End result: 100% strongly typed agent written code, at least one kind of slop gone.