5 ms·
>"I spent 20m halfheartedly looking for an example I could use to discredit a stranger online. Every programming language but python is wrong." This is a reall
by cthalupa 8y ago
>"I spent 20m halfheartedly looking for an example I could use to discredit a stranger online. Every programming language but python is wrong."
This is a really uncharitable interpretation of what he did. It was specifically mentioned as a scripting language, and parsing command line arguments is frequently necessary for scripts.
He then compared the hello world examples for the two most popular command line argument libraries. This is hardly going out of his way to find some bizarre corner case examples - it's the primary example for one of the most important libraries for the advocated use case. He never said anything about any programming languages besides Python and F#.
You can disagree with him without twisting his argument around.
- KirinDave 8y ago> This is a really uncharitable interpretation of what he did. It was specifically mentioned as a scripting language, and parsing command line arguments is frequently necessary for scripts. Is it? Why should be beholden to assuming positive intent when the post is clearly being equally dismissive? This is a social contract and when it's broken, the rules change. > He then compared the hello world examples for the two most popular command line argument libraries. And quite frankly, the F# code seems much better than that nightmarishly overdense 5-kwarg soup that uses stringly typed kwargs that if you omit are sometimes valid. The F# version shows how to do custom error handling and even hints at custom arg parsing, while the Python version is deliberately avoiding anything even remotely complex. It still ends up being an ugly pile of easy-to-typo kwarg code. > You can disagree with him without twisting his argument around. "He" can disagree after doing even a tiny bit of research, though. "This code is shorter," is also a fascile argument that any Pythonista will immediate dissmiss with smug harrumpus about readability and intuitiveness. It's a disingenuous argument, front to back.
- joshuamorton 8y agoThe two examples parse exactly the same set of arguments, so your claim that the python one ignores complexity seems naive, whether or not this was an intentional oversight im unsure of. Or perhaps it's just significantly simpler ;) My problems with the F# example: 1. It internally rewrites the argument names. "Data" becomes "--data". Who knows how I can get a short flag (-d) in f# land. 2. You don't declare things at once. You define all the arguments the. You define all the descriptions, etc. This isn't the fault of the language necessarily, but this API is bad. It's highly repetitive (each modification to an argument requires a new match expression it seems, that's gross). 3. It's unclear if and how this is extensible. I can continue to decorate main to add more args (for example if I wrap an existing tool and define additional flags), in python in an obvious way. This is not obvious in F#. This compounds #2. Your objection about kwargs isn't particularly compelling. Kwargs are exactly as "stringly" typed as method names, which is exactly how you're doing modifications in F# (or Java or anything else). And density of the python is trivial to fix by adding newlines. As an aside, I'm the third (or fourth?) to tell you that your responses appear incredibly disingenuous. And that you are the one acting dismissively, not the post you originally responded to. I don't see any universe where going to the effort of comparing the two languages in question in a reasonable benchmark and sharing it is anything approximately dismissive.
- KirinDave 8y agoIn advance, I apologize for fisking your post. I did it simply because I wanted to provide a lot more information than I think you're interested in, and this is the best typesetting option I have. > The two examples parse exactly the same set of arguments, so your claim that the python one ignores complexity seems naive, whether or not this was an intentional oversight im unsure of. Or perhaps it's just significantly simpler ;) You ignored that bit of my post. I said the F# one hints at how to do more complex things. The click example (I use click all the time, by the way) has completely different methods for introducing other constructs or doing custom logic. The F# version just uses lambdas (a sore spot on Python) to do this. > 1. It internally rewrites the argument names. "Data" becomes "--data". Who knows how I can get a short flag (-d) in f# land. You'd annotate it. This is why I said the original example offer was poorly researched. They literally didn't scroll down less than 2 screen widths. You didn't even bother to check either. You'd add an annotation to the delclaration such as: [<AltCommandLine("-d")>] > 2. You don't declare things at once. You define all the arguments the. You define all the descriptions, etc. This isn't the fault of the language necessarily, but this API is bad. It's highly repetitive (each modification to an argument requires a new match expression it seems, that's gross). You seem to have chopped this up editing it, but I think the gist is that there is a repeated value here in the match. You seem to think that's bad because of DRY principles and because it's easy to make an error. It is not easy to make an error. F# is statically typed and checked. It'd be an awful decision in a language with no static correctness checking, like Python. In F#, the compiler will flag you with a non-exhaustive pattern match error and tell you which values you're missing! You can read more about that here: https://fsharpforfunandprofit.com/posts/correctness-exhaustive-pattern-matching/ https://fsharpforfunandprofit.com/posts/correctness-exhausti... As for the decls, this is fine. Not only does the compiler have your back, but it's quite normal to have a fair amount of separation between your main loop and your arg parsing. In fact, you almost certainly have it in F# due to the way args are loaded. You'll usually have a separate file containing those data decls so that you can use them without importing your main loop (F# has a bit of ugliness here imo; modules have a defined linear load error and you can't import code in complex graphs). Remember, unlike a stringly-typed map you'e getting back a strongly typed, bespoke discriminated unions that contains exactly the values you expect. If you'd prefer map-key syntax instead of a typechecked function map (because you hate autocomplete and static correctness) to provide your usage strings... then it's trivial to do that in F#. F#'s documentation is awesome at avoiding incidentals and focusing on the task at hand though. > 3. It's unclear if and how this is extensible. I can continue to decorate main to add more args (for example if I wrap an existing tool and define additional flags), in python in an obvious way. This is not obvious in F#. This compounds #2. Since you don't know F#, is it that surprising it's unclear? But anyways... You don't want it to be extensible. You want to edit the struct and then also edit the error handling and specifications. You want to give the compiler a chance to catch your errors. If you remove an option, the compiler will tell you every place you need to change it. If you add one, nothing will break except your usage map and your error handler (and possibly in extremely weird custom parse cases that can come up, but don't custom parse over unquoted strings and you're fine). > Your objection about kwargs isn't particularly compelling. Kwargs are exactly as "stringly" typed as method names, which is exactly how you're doing modifications in F# (or Java or anything else). I think you misunderstand how this works. Incorrect java method names are a compile time error. In Python a missing kwarg is a runtime error. In some cases, a python linter can catch it via heuristics. That's not always the case, particularly across library or communication boundaries. > And density of the python is trivial to fix by adding newlines. The same could be done for the F# variant by removing them. That doesn't mean it's a good idea. > As an aside, I'm the third (or fourth?) to tell you that your responses appear incredibly disingenuous. I don't think I've been at all dishonest about my intentions. I don't like Python, I think this new PEP makes an already bad, I think the justification for it is bad, and everything in Python would be better without it. What am I being "disingenuous" about? Am I engaging with you dishonestly? > And that you are the one acting dismissively, not the post you originally responded to. I bad attempt at dismissing F# by refusing to even read one tutorial page by a Python user in 2018 does not deserve anything but derision. Your attempt to defend it without even checking to see what the author did is not quite so bad, so I'm being more civil with this response, but I think it's in a similar kind of Pythonista conversation that goes, "I don't know and I don't want to know, because Python is fine." > I don't see any universe where going to the effort of comparing the two languages in question in a reasonable benchmark and sharing it is anything approximately dismissive. Well hopefully this post has helped illustrate some of the considerations that make that comparison more reasonable? I genuinely mean that! I could have skipped over or not explained the part about why the separation doesn't matter, how F#'s compiler has a linear load order, or why it's not problematic (and in fact desirable and autocomplete-assisted) for a bit of repetition. I think it's a mistake to approach language comparisons looking for ways to dismiss it until you've written at least a few trivial programs in said language. I've written tons of Python and a fair sum of F#. And honestly, I'm not a huge fan of Argu as a library compared to something like optparse-applicative from Haskell. But it's much more serviceable than this comparison implies. I particularly dislike Python's solution because it's a series of kwarg invocations with signature overlap. I've been burned by this in the past, and I dislike the, "here is the secret method that does EXACTLY what you want" approach that Python decorator patterns usually demand.