TE
科技回声
首页24小时热榜最新最佳问答展示工作
GitHubTwitter
首页

科技回声

基于 Next.js 构建的科技新闻平台,提供全球科技新闻和讨论内容。

GitHubTwitter

首页

首页最新最佳问答展示工作

资源链接

HackerNews API原版 HackerNewsNext.js

© 2025 科技回声. 版权所有。

Why static languages suffer from complexity

213 点作者 Lapz超过 3 年前

27 条评论

Animats超过 3 年前
Fascination with type systems does not seem to be all that useful in practice. Go has a minimal type system, and is able to do much of Google&#x27;s internal server side work.<p>Most of the problems that cause non-trivial bugs come from invariant violations. At point A, there&#x27;s some assumption, and way over there at point B, that assumption is violated. That&#x27;s an invariant violation.<p>Type systems prevent some invariant violations. Because that works, there are ongoing attempts to extend type systems to prevent still more invariant violations. That creates another layer of confusing abstraction. Some invariants are not well represented as types, and trying makes for a bad fit. What you&#x27;re really trying to do is to substitute manual specification of attributes for global analysis.<p>The Rust borrow checker is an invariant enforcer. It explicitly does automatic global analysis, and reports explicitly that what&#x27;s going on at point B is inconsistent with what point A needs. This is real progress in programming language design, and is Rust&#x27;s main contribution.<p>That&#x27;s the direction to go. Other things might be dealt with by global analysis, Deadlock detection is a good example. If P is locked before Q on one path, P must be locked before Q on all paths. There must be no path that leads to P being locked twice. That sort of thing. Rust has a related problem with borrows of reference counted items, which are checked at run time and work a lot like locks. Those potentially have a double-borrow problem related to program flow. I&#x27;ve heard that someone is working on that for Rust.
评论 #29999377 未加载
评论 #30000548 未加载
评论 #29999566 未加载
评论 #29999421 未加载
评论 #30003443 未加载
评论 #30000219 未加载
评论 #30004633 未加载
评论 #30001629 未加载
评论 #30002866 未加载
armchairhacker超过 3 年前
&quot;Why not add X feature? If people don&#x27;t want to use X, they just don&#x27;t, and there are basically 0 downsides.&quot;<p>In theory this is true. If the compiler is decent, compile times and analysis shouldn&#x27;t really be affected. Maybe libraries will use X but otherwise they would use a manual implementation of X anyways.<p>But in practice developers misuse features, so adding a feature actually leads to worse code. It also creates a higher learning curve, since you have to decide whether to use a new feature or just re-implement it via old features. See: C++ and over-engineered Haskell. So each feature has a &quot;learnability cost&quot;, and only add features which are useful enough to outweigh the cost.<p><i>But</i> most features actually are useful, at least for particular types of programs. It&#x27;s much harder to write an asynchronous program without some form of async; it&#x27;s much harder to write a program like a video game without objects. This may be controversial, but I really don&#x27;t like Go and Elm (very simple languages) because I feel like have to write so much boilerplate vs. other languages where I could just use an advanced feature. And this boilerplate isn&#x27;t just hard to create, it&#x27;s hard to maintain because small changes require rewriting a lot of code.<p>So ultimately language designers need to balance number of features with expressiveness: the goal is to use as few simple but powerful features to make your language simple but really expressive. And different languages for different people. Personally I like working with Java and Kotlin and Swift (the middle languages in the author&#x27;s meme) because I can establish coding conventions and stick to them, C++ and Haskell are too complicated and it&#x27;s harder to figure out and stick to the &quot;ideal&quot; conventions.
评论 #29998667 未加载
评论 #29999596 未加载
评论 #29999789 未加载
arc619超过 3 年前
This entire article can be summarised as &quot;compile time stuff should use the same language as run time&quot;.<p>I guess the author just hasn&#x27;t encountered Nim before, where anything becomes compile time by just assigning to a const, and macros have access to the real AST without substitution. Macros also allow compile time type inspection, as they are a first class citizen rather than tacked on.<p>The compile time print, AFAICT, already exists in Nim as the `&amp;` macro in strformat. That lets you interpolate what you like at compile time, and supports run time values too.
评论 #29999294 未加载
AndyKelley超过 3 年前
This article incorrectly states that Zig has &quot;colored&quot; `async` functions. In reality, [Zig async functions do not suffer from function coloring](<a href="https:&#x2F;&#x2F;kristoff.it&#x2F;blog&#x2F;zig-colorblind-async-await&#x2F;" rel="nofollow">https:&#x2F;&#x2F;kristoff.it&#x2F;blog&#x2F;zig-colorblind-async-await&#x2F;</a>).<p>&gt; Yes, you can write virtually any software in Zig, but should you? My experience in maintaining high-level code in Rust and C99 says NO.<p>Maybe gain some experience with Zig in order to draw this conclusion about Zig?
评论 #30007280 未加载
评论 #30003981 未加载
preseinger超过 3 年前
&gt; I cannot imagine a single language without the if operator, but only a few PLs accommodate full-fledged trait bounds, not to mention pattern matching. This is <i>inconsistency</i> . . .<p>How?<p>&gt; Sometimes, software engineers find their languages too primitive to express their ideas even in dynamic code. But they do not give up . . .<p>Is this a failure of the language, or a failure of the engineer?<p>&gt; If we make our languages fully dynamic, we will win biformity and inconsistency,[^] but will imminently lose the pleasure of compile-time validation and will end up debugging our programs at mid-nights . . . One possible solution I have seen is dependent types. With dependent types, we can parameterise types not only with other types but with values, too.<p>Types are a productive abstraction&#x2F;model in programming languages. One of many. Each has its strengths and weaknesses; each is appropriate in some circumstances and not in others. Types are not the solution to all problems, any more than currying or OOP or whatever else is.
评论 #29997708 未加载
chubot超过 3 年前
Nice article! Highly related discussions:<p><a href="https:&#x2F;&#x2F;github.com&#x2F;fsharp&#x2F;fslang-suggestions&#x2F;issues&#x2F;243#issuecomment-916079347" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;fsharp&#x2F;fslang-suggestions&#x2F;issues&#x2F;243#issu...</a><p><a href="https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;ProgrammingLanguages&#x2F;comments&#x2F;placo6&#x2F;don_syme_explains_the_downsides_of_type_classes&#x2F;" rel="nofollow">https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;ProgrammingLanguages&#x2F;comments&#x2F;placo...</a><p>F# designer Don Syme is making the &quot;biformity&quot; argument, e.g. needing a debugger for compile time as well as runtime.<p>and<p><i>Syme &amp; Matsakis: F# in the Static v. Dynamic divide</i> <a href="https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;ProgrammingLanguages&#x2F;comments&#x2F;rpcm65&#x2F;syme_matsakis_f_in_the_static_v_dynamic_divide&#x2F;" rel="nofollow">https:&#x2F;&#x2F;old.reddit.com&#x2F;r&#x2F;ProgrammingLanguages&#x2F;comments&#x2F;rpcm6...</a><p>I still think something an application language with something like Zig&#x27;s comptime would fill a big niche. (As opposed to a systems language.)
devit超过 3 年前
Yeah, the current problem is that Idris code is far less efficient than Rust code, because Idris boxes everything and erases all types, and also Idris&#x27;s support for borrowing seems less powerful than Rust (it lacks first-class mutable borrows as far as I can tell).<p>It seems that fixing this is a research problem, which would lead to the holy grail of programming languages, i.e. an ultimate language that is as expressive as Idris and as efficient as Rust, and is thus essentially perfect.
评论 #29998700 未加载
评论 #29998529 未加载
评论 #29998809 未加载
评论 #29998262 未加载
preordained超过 3 年前
Having used Clojure for a while now, I will say having 90% of things be a primitive, map, or vector goes a long way in and of itself. A lot of types concocted in a more conventional language just don&#x27;t need to exist, IMO, and they create so much baggage around themselves.
评论 #30000573 未加载
评论 #30004871 未加载
评论 #29999439 未加载
Zababa超过 3 年前
In the SML&#x2F;OCaml world there&#x27;s something like that: there is a difference between types and modules, and functions (from types to types) and functors (from module to module). Work was done on 1ML to unify everything: <a href="https:&#x2F;&#x2F;people.mpi-sws.org&#x2F;~rossberg&#x2F;1ml&#x2F;" rel="nofollow">https:&#x2F;&#x2F;people.mpi-sws.org&#x2F;~rossberg&#x2F;1ml&#x2F;</a>. An extract:<p>&gt; In this &quot;1ML&quot;, functions, functors, and even type constructors are one and the same construct; likewise, no distinction is made between structures, records, or tuples. Or viewed the other way round, everything is just (&quot;a mode of use of&quot;) modules. Yet, 1ML does not require dependent types, and its type structure is expressible in terms of plain System Fω, in a minor variation of our F-ing modules approach.<p>&gt; An alternative view is that 1ML is a user-friendly surface syntax for System Fω that allows combining term and type abstraction in a more compositional manner than the bare calculus.<p>On the other hand, from the &quot;engineer&quot; point of view, all abstractions melting into one may not be desirable. It&#x27;s nice to be able to use weak abstractions for simple stuff and powerful abstractions for more powerful stuff. Being exposed to the full complexity of your language all the time sounds like a recipe for disaster.
batrachos超过 3 年前
I dislike the phrase &#x27;dynamic language&#x27; and especially dislike the phrase &#x27;static language&#x27;. We should say &#x27;dynamically typed&#x27; or &#x27;statically typed&#x27;, because &#x27;static&#x27; languages are the site of major dynamism.
评论 #29998309 未加载
dnautics超过 3 年前
I didn&#x27;t see the article touch on the &quot;why&quot; explicitly, but: zig really has the chance to square this circle for low level languages, since there is duck-typed type-inferenced-coercion in places where it makes sense. Completely correct about zig not necessarily being good for higher level stuff, but I think (dynamic) HLLs have been converging on dealing with this using static typechecking, with varying levels of success
评论 #30005224 未加载
zmmmmm超过 3 年前
The problem I find with static typing is that it so easily leads you over-specifying the requirements &#x2F; constraints. In fact, it makes such a virtue out of that over-specification that many people would consider it a best practice to do so.<p>For example, perhaps my `calculate_price` function only depends on 2 attributes of the order which has 65 attributes. Am I creating a 2-element data type for that function to process? no! I&#x27;m specifying that it processes an Order data type, with all its 65 elements. But implicitly then I&#x27;m saying the function has 65 input parameters of all these specific types and nobody can call it now without providing them all. What a pain! Huge amount of extra code, refactoring, unit testing, because of this.<p>So either you end up with a cambrian explosion of micro-types or you have these way overspecified interfaces everywhere.<p>Compare with dynamic languages (or structural typing, Go etc) that only care that things &quot;quack like a duck&quot;. The calculate_price function doesn&#x27;t care what object you give it, as long as it has the two attributes it needs. Now I can unit test `calculate_price` with a 2-element object rather than needlessly creating the 23 irrelevant required elements of a valid Order.<p>I think a lot could be solved with culture shift. Where data types are really known and locked in, use the crap out of them. As soon as things get ambiguous or flexible, go right ahead and specify that your function takes a Map&lt;String,Object&gt;. If a useful concrete interface emerges at some point factor it out then. The problem is that this is really frowned upon in a lot of places.
评论 #30001821 未加载
评论 #30001593 未加载
评论 #30001476 未加载
评论 #30001700 未加载
评论 #30000879 未加载
评论 #30002039 未加载
评论 #30005526 未加载
评论 #30001690 未加载
dleslie超过 3 年前
I&#x27;m unfamiliar with one of the language logos in the meme graph at the bottom: what&#x27;s the red swooshy thing beside zig?
评论 #29997059 未加载
评论 #29997127 未加载
评论 #29997094 未加载
评论 #29997055 未加载
tempodox超过 3 年前
This article spends many words to say, “there is no silver bullet”.<p>But dynamically typed languages produce at least the same amount of accidental complexity, just in different ways.
评论 #29998911 未加载
评论 #29999711 未加载
lowbloodsugar超过 3 年前
&quot;We might want to zip our car with their car...&quot;<p>We do or we don&#x27;t. There is no &quot;might&quot;. Spending money on &quot;might&quot; has been the death of many projects.<p>If we didn&#x27;t, and now we do, we could write a fn to map the car to parts, or we could define the car struct in terms of its parts, or we could just do away with the car altogether.<p>But far more valuable would be an analysis of what changed about the requirements that the model no longer works.<p>Now, don&#x27;t get me wrong: I&#x27;d love a better language, and by better I mean &quot;as fast as assembly but &#x27;dynamic&#x27;&quot;. The problem is that, at the end of the day, all compilers are just &quot;premature optimizations&quot; or perhaps &quot;willing premature optimizations&quot;. We could all be happily programming in smalltalk or build a runtime using predicate logic, but a) the number of people who could program in it is vanishingly small and b) it would be fucking slow. These languages don&#x27;t solve a problem that I have, or rather they don&#x27;t solve a problem that I don&#x27;t already have a far better solution for. They solve a problem that academics have.
chriswarbo超过 3 年前
I think the comparison between printf in Idris and Zig is a little off, since the Idris version defines an intermediate datastructure, and hence requires extra parsing and interpreting functions for it. That&#x27;s a <i>nice</i> approach, but the Zig version is operating directly on characters, so it&#x27;s a bit apples-to-oranges.<p>We can get a more direct Idris implementation by inlining the parser (toFmt) into the interpreter (PrintfType). That lets us throw away `Fmt`, `toFmt`, etc. to just get:<p><pre><code> PrintfType : (fmt : List Char) -&gt; Type PrintfType (&#x27;*&#x27; :: xs) = ({ty : Type} -&gt; Show ty =&gt; (obj : ty) -&gt; PrintfType xs) PrintfType ( x :: xs) = PrintfType xs PrintfType [] = String printf : (fmt : String) -&gt; PrintfType (unpack fmt) printf fmt = printfAux (unpack fmt) [] where printfAux : (fmt : List Char) -&gt; List Char -&gt; PrintfType fmt printfAux (&#x27;*&#x27; :: fmt) acc = \obj =&gt; printfAux fmt (acc ++ unpack (show obj)) printfAux ( c :: fmt) acc = printfAux fmt (acc ++ [c]) printfAux [] acc = pack acc</code></pre>
评论 #29999601 未加载
评论 #29998549 未加载
erichocean超过 3 年前
FWIW, I&#x27;ve been developing code directly in MLIR recently, and in MLIR &quot;Comparing types is cool&quot; is indeed true.<p>It&#x27;s amazing what you can do when you have compiler transformations and targets always available.<p>Suddenly, &quot;little DSLs&quot; (MLIR dialects) don&#x27;t seem so bad, since they are defined the same way and map in semantically-sound ways to lower-level dialects. You can have dedicated dialects, like Halide, for doing something as concrete as image processing kernels.<p>Oh, and you can output those kernels to both the CPU and GPU, including automatically introducing async functions, host-side sync barriers, etc. Good luck doing that automatically with a general purpose programming language and a combination of macros, AST manipulations, and derived types! You really need a compiler to stay sane.<p>&gt; <i>&quot;Programming languages ought to be rethought.&quot;</i><p>Indeed.
评论 #30001539 未加载
aabbcc1241超过 3 年前
One way to do dynamic macro in static type language is to generate the source code using the host language as separate build process before the compilation of hand-written and generated source code.<p>For example in Typescript, I use tsc-macro to run &quot;*.macro.ts&quot;, they can import any functions and modules just like normal source code. And their evaluated result are saved as &quot;*.ts&quot;<p>The generated ts are then compiled alone with other hand-written typical source files into js for deployment and execution.
honkycat超过 3 年前
Great article, made me think! However, I think it needs to be trimmed down. Making your argument in the final paragraph of the article is not great.<p>Hoist the &quot;Final Words&quot; section to the top and make it a &quot;tldr&quot; introduction, that way your reader can begin with a high level understanding of your argument, which you can hone and refine as you progress.
mbrodersen超过 3 年前
Almost all software running the world is written in statically typed languages. This is not by accident or because developers don’t know better. Every few months on HN somebody will make some new claim about why dynamically typed languages are somehow better. But the truth is that statically typed languages have won in the market place for real world software. And I don’t see anything changing that.
评论 #30003090 未加载
评论 #30005401 未加载
ModernMech超过 3 年前
Ugh, I know I&#x27;m getting old when I don&#x27;t understand the memes.
adamddev1超过 3 年前
I wonder where TypeScript would fall on this language continuum?
评论 #29998603 未加载
AtNightWeCode超过 3 年前
This is some kind of joke, right?
dandotway超过 3 年前
So whenever I have to study someone else&#x27;s &#x27;dynamic&#x27; python I encounter this sort of thing:<p><pre><code> def foo(bar, baz): bar(baz) ... </code></pre> What the heck is &#x27;bar&#x27; and &#x27;baz&#x27;? I deduce no more than &#x27;bar&#x27; can be called with a single &#x27;baz&#x27;. I can&#x27;t use my editor&#x2F;IDE to &quot;go to definition&quot; of bar&#x2F;baz to figure out what is going on because everything is dynamically determined at runtime, and even<p><pre><code> grep -ri &#x27;\(foo\|bar\|baz\)&#x27; --include \*.py </code></pre> Won&#x27;t tell me much about foo&#x2F;bar&#x2F;baz, it will only start a hound dog on a long and windy scent trail.
评论 #29997901 未加载
评论 #29997855 未加载
评论 #29998393 未加载
评论 #29998111 未加载
评论 #29997753 未加载
评论 #29998130 未加载
评论 #29997808 未加载
评论 #29998739 未加载
评论 #29998630 未加载
评论 #29998161 未加载
评论 #29998178 未加载
guidorice超过 3 年前
Best.Programmer.Art.Ever
pyrale超过 3 年前
I must admit I was very surprised so see what started as a static-types rant ending up extolling the merits of Idris.
seanw444超过 3 年前
I really want to know where I can find quality programming memes like these. Not just the generic &quot;haha language ___ is bad, nerd&quot; memes.