I was never a huge fan of dynamic typing just because of all the unintentional consequences and bugs it could introduce. They weren't worth the payoff of the supposed benefits. I was going to...
I was never a huge fan of dynamic typing just because of all the unintentional consequences and bugs it could introduce. They weren't worth the payoff of the supposed benefits.
I was going to stick to C# because of this, but really think languages will all start handling it more like F# (which infers the type wherever possible, errors if it can't until you type it).
Most of their examples just seem to be a much higher level of the discovery I already went through.
I think the thing I'm missing here is why any of the author's proposed features depend on dynamic typing. For example: Lots of statically typed languages have callable non-function objects! Fewer...
I think the thing I'm missing here is why any of the author's proposed features depend on dynamic typing. For example:
We can replace a function with an object that can be called for the exact same behavior, but also gives us an information sidechannel.
Lots of statically typed languages have callable non-function objects! Fewer let you replace functions, but that's not a dynamic typing thing, that's a "considering globally-defined functions to be constants" thing. That the two tend to correlate is a property of how languages influence each other, not of the type system.
At a fundamental level what I really want is a language that is all-pointers and has managed memory. Dealing with Rust memory constraints is annoying. Sometimes you need to operate at that level,...
At a fundamental level what I really want is a language that is all-pointers and has managed memory. Dealing with Rust memory constraints is annoying. Sometimes you need to operate at that level, but mostly it's not necessary. Most dynamically typed languages are easier to work in because the size of each variable/parameter is constant, thus making every variable a universal value slot. In addition I don't want to think much about when memory is allocated or released because the stuff I work with doesn't operate in "real time".
My favorite dynamically typed language is TypeScript. Any person pretending like they don't need to declare the types in their dynamically typed code is a fool. Thankfully TypeScript gives you a few escape-hatches. JSON.parse returns any. Thrown objects are unknown. Maybe you know a few of the most likely options for a parameter but there are others of unknown type.
That's dynamic typing and not something you can do as easily in a statically typed language. A statically typed language might have a void * type of escape hatch. But in C there's no built in reflection so you're at a dead end unless you know what the type is. Static languages with reflection kind of approach this same solution from the other side. Actually, I feel like we're slowly getting towards a middle point. We've taking dynamic languages and given developers the tools to make them behave more like they're static. And we've taken static languages and given developers the tools to make them behave more like they're dynamic.
This Python code: x = 1 is equivalent (in spirit) to this C code: int* x = (int *)malloc(sizeof(int)); *x = 1; In Python, and some other dynamic languages, there is no equivalent of a simple int...
This Python code:
x=1
is equivalent (in spirit) to this C code:
int*x=(int*)malloc(sizeof(int));*x=1;
In Python, and some other dynamic languages, there is no equivalent of a simple int x. Instead of values you have pointers. Instead of pointers you have pointers to pointers. Bad for performance but good for ergonomics.
This gets unnecessarily deep into implementation details. I suppose there could be a better way to describe what it is I like. Perhaps universal polymorphism? In NodeJS (well, v8) they use NaN boxing. Everything is an IEEE double. Even the pointers. They encode pointers under the vast range of valid NaN bit patterns. Floats, ints, booleans, null, undefined and pointers are the top level concepts held in a NaN box.
Reading about how Rust prevents data races at compile time is kind of blowing my mind: https://doc.rust-lang.org/1.8.0/book/references-and-borrowing.html
You've probably heard of OCaml, but I think it's worth mentioning. Rust's first compiler was done in OCaml, and the project was born to make a "C-like OCaml", this is because of OCaml's ML-like...
At a fundamental level what I really want is a language that is all-pointers and has managed memory. Dealing with Rust memory constraints is annoying.
You've probably heard of OCaml, but I think it's worth mentioning. Rust's first compiler was done in OCaml, and the project was born to make a "C-like OCaml", this is because of OCaml's ML-like syntax which feels off-putting to most people.
On the bright side, you have a really robust type system, with inference, generalized algebraic datatypes (which are more expressive that the union you just described) along pattern matching; the uniform memory representation (most types are pointers, integers are the only exception); and the garbage collector is optimized for dealing with a big influx of allocations that this design causes. It has a heap for short-lived allocations, and another for long-term ones.
Also the compiler is really fast and the binaries are quite optimized, they're comparable to Go, the tooling might not be there yet, because its academic roots, but now it's light-years ahead compared to 5 years ago, when I started using it.
OCaml tooling has definitely improved massively. There are also some cool new functional programming languages with C-style syntax, for example Gleam which runs on BEAM (the VM Erlang uses)....
OCaml tooling has definitely improved massively. There are also some cool new functional programming languages with C-style syntax, for example Gleam which runs on BEAM (the VM Erlang uses). There's also some alternative syntax for OCaml, e.g. Reason (unfortunately the community split here and there's like 10 projects forked from the same thing with similar names doing slightly different things).
Is this not just a discriminated union like in F#? edit- On reread you might be referring to the Unknown type throwing, but even that I think can be done in C/F#, so i'm unsure.
Is this not just a discriminated union like in F#?
edit-
On reread you might be referring to the Unknown type throwing, but even that I think can be done in C/F#, so i'm unsure.
The higher order programs they describe in the post seem very similar to what aspect oriented programming does. It allows to basically inject behaviour by specifying cut points. In the Java world...
The higher order programs they describe in the post seem very similar to what aspect oriented programming does. It allows to basically inject behaviour by specifying cut points. In the Java world this was popular (not entirely sure?) for a bit in the late 00s early 10s. Yes it has it's uses, but in practice seems fairly rarely useful for application development other than by consuming/using existing libraries (e.g. lombok).
Main point is that the type of behavior the author is advocating isn't exclusive to dynamically typed languages.
I was never a huge fan of dynamic typing just because of all the unintentional consequences and bugs it could introduce. They weren't worth the payoff of the supposed benefits.
I was going to stick to C# because of this, but really think languages will all start handling it more like F# (which infers the type wherever possible, errors if it can't until you type it).
Most of their examples just seem to be a much higher level of the discovery I already went through.
I think the thing I'm missing here is why any of the author's proposed features depend on dynamic typing. For example:
Lots of statically typed languages have callable non-function objects! Fewer let you replace functions, but that's not a dynamic typing thing, that's a "considering globally-defined functions to be constants" thing. That the two tend to correlate is a property of how languages influence each other, not of the type system.
For example, here's a direct C++ translation of the Python example from the article, using a mutable function reference since you can't overwrite the function directly.
At a fundamental level what I really want is a language that is all-pointers and has managed memory. Dealing with Rust memory constraints is annoying. Sometimes you need to operate at that level, but mostly it's not necessary. Most dynamically typed languages are easier to work in because the size of each variable/parameter is constant, thus making every variable a universal value slot. In addition I don't want to think much about when memory is allocated or released because the stuff I work with doesn't operate in "real time".
My favorite dynamically typed language is TypeScript. Any person pretending like they don't need to declare the types in their dynamically typed code is a fool. Thankfully TypeScript gives you a few escape-hatches.
JSON.parse
returnsany
. Thrown objects areunknown
. Maybe you know a few of the most likely options for a parameter but there are others of unknown type.That's dynamic typing and not something you can do as easily in a statically typed language. A statically typed language might have a
void *
type of escape hatch. But in C there's no built in reflection so you're at a dead end unless you know what the type is. Static languages with reflection kind of approach this same solution from the other side. Actually, I feel like we're slowly getting towards a middle point. We've taking dynamic languages and given developers the tools to make them behave more like they're static. And we've taken static languages and given developers the tools to make them behave more like they're dynamic.What do you mean by this? As in a language that allows you to read/write to arbitrary memory locations?
This Python code:
is equivalent (in spirit) to this C code:
In Python, and some other dynamic languages, there is no equivalent of a simple
int x
. Instead of values you have pointers. Instead of pointers you have pointers to pointers. Bad for performance but good for ergonomics.This gets unnecessarily deep into implementation details. I suppose there could be a better way to describe what it is I like. Perhaps universal polymorphism? In NodeJS (well, v8) they use NaN boxing. Everything is an IEEE double. Even the pointers. They encode pointers under the vast range of valid NaN bit patterns. Floats, ints, booleans,
null
,undefined
and pointers are the top level concepts held in a NaN box.It sounds like what you want is a statically typed language with an "any" type, but I'm still not really sure?
That would be nice, as long as the any type doesn’t operate differently than the other types. The unknown type from TypeScript is also very useful.
Reading about how Rust prevents data races at compile time is kind of blowing my mind: https://doc.rust-lang.org/1.8.0/book/references-and-borrowing.html
You've probably heard of OCaml, but I think it's worth mentioning. Rust's first compiler was done in OCaml, and the project was born to make a "C-like OCaml", this is because of OCaml's ML-like syntax which feels off-putting to most people.
On the bright side, you have a really robust type system, with inference, generalized algebraic datatypes (which are more expressive that the union you just described) along pattern matching; the uniform memory representation (most types are pointers, integers are the only exception); and the garbage collector is optimized for dealing with a big influx of allocations that this design causes. It has a heap for short-lived allocations, and another for long-term ones.
Also the compiler is really fast and the binaries are quite optimized, they're comparable to Go, the tooling might not be there yet, because its academic roots, but now it's light-years ahead compared to 5 years ago, when I started using it.
OCaml tooling has definitely improved massively. There are also some cool new functional programming languages with C-style syntax, for example Gleam which runs on BEAM (the VM Erlang uses). There's also some alternative syntax for OCaml, e.g. Reason (unfortunately the community split here and there's like 10 projects forked from the same thing with similar names doing slightly different things).
Is this not just a discriminated union like in F#?
edit-
On reread you might be referring to the Unknown type throwing, but even that I think can be done in C/F#, so i'm unsure.
Rust has them as well. With enough compile time code gen your static language can be pretty dynamic.
C# is pretty dynamic isn’t it? I’ve actually never used it.
C# is statically typed in general, but it has support for dynamic types via the
dynamic
keyword.The higher order programs they describe in the post seem very similar to what aspect oriented programming does. It allows to basically inject behaviour by specifying cut points. In the Java world this was popular (not entirely sure?) for a bit in the late 00s early 10s. Yes it has it's uses, but in practice seems fairly rarely useful for application development other than by consuming/using existing libraries (e.g. lombok).
Main point is that the type of behavior the author is advocating isn't exclusive to dynamically typed languages.