Que?
Que?
Python 3.9.0 (default, Oct 10 2020, 11:40:52)
[Clang 11.0.3 (clang-1103.0.32.62)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1+"1"
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unsupported operand type(s) for +:
'int' and 'str'
While a weakly typed dynamic language like JS will allow for it Welcome to Node.js v16.0.0.
Type ".help" for more information.
> 1 + "1"
'11'JavaScript's more forgiving, and often surprising, implicit conversions are still rigidly-defined .
Remember that implicit conversions should never (ostensibly) throw any exception or cause any errors because implicit conversion should always succeed because it should only be used to represent an obvious and safe narrowing-conversion. A narrowing-conversion necessarily involves data-loss, but it's safe because all of the data needed by the rest of the program is being provably retained.
This doesn't feel like a very useful definition. What languages would fall under the category of "weakly typed" by your definition? I can only think of C, and even that is only true for a subset of the language (when you're messing about with pointers).
> Remember that implicit conversions should never (ostensibly) throw any exception or cause any errors because implicit conversion should always succeed because it should only be used to represent an obvious and safe narrowing-conversion.
> const fun = (x, y) => (x + y) / y
> fun(1, 2)
1.5
> fun("1", 2)
6
No exception? Yes. No error? Nope, implicit conversion absolutely just caused an error. If I got that "1" from an input field and forgot to cast it to an int, I want to be told at the soonest possible juncture, I don't want to rely on me noticing that the result doesn't look right. As it is, "weak" feels like a good word for the types here. They don't hold their form well.29.5 Types Versus Safety
"Programming and Programming Languages"
https://papl.cs.brown.edu/2020/safety-soundness.html#%28part...
I think it's more germane to refer to that as weak implicit type casting.
class A(random.choice([B, C]):
... class Rectangle:
var w,h
class Square(Rectangle if w == h):
...
You could then overload functions/methods on both `Square` and `Rectangle` and it would call the correct overload depending on the runtime values of `w` and `h`.The last thing: being able to edit program code, add new types/members/functionality and so-on while it's running... that's not really a language limitation nor typing-system limitation either: that's just good tooling that is able to hot-swap executable code after the process has already started. Visual Studio has had "Edit & Continue" in debugging sessions for almost 3 decades now, and the runtime build system used by ASP.NET means that source code and raw aspx/cshtml views can still be FTP'd up to production and just work, because .NET supports runtime compilation.
------------
For ordinary business software, where the software's focus is on data-modelling and data-transforming-processes, so all these programs basically just pass giant aggregates of business data around, so strong-typing is essential to ensure we don't lose any properties/fields/values as these aggregate objects travel through the software-proper. In this situation there is absolutely no "expressiveness" that's could be gained by simply giving up on type-correctness and instead rely on unit tests (and hope you have 100% test coverage).
It's more complex than that. The language absolutely has to define these operations for them to make any sense. Modifying some code inside a function is the easy case, and supported by many environments. Modifying types is much more difficult, and usually not supported (.NET and JVM do not support any kind of type modification - neither field nor function). I'm not sure if the C++ debugger can handle this either. Common Lisp can do it, and it actually defines how existing objects behave if their type changes.
There is also ways of dealing with this in dynamic languages. For example, Clojure has clojure.spec that achieves the same results, but without relying on strong typing.
In the end, it's all tradeoffs. There is no "one solution" that will be perfect for everything.
https://vvvvalvalval.github.io/posts/what-makes-a-good-repl....
> If you're not familiar with Clojure, you may be surprised that I describe the REPL as Clojure's most differentiating feature: after all, most industrial programming languages come with REPLs or 'shells' these days (including Python, Ruby, Javascript, PHP, Scala, Haskell, ...). However, I've never managed to reproduced the productive REPL workflow I had in Clojure with those languages; the truth is that not all REPLs are created equal.
Basically, the "REPL" you usually call a REPL is in fact a shell, and not a REPL as normally used in lisp languages.
By contrast, most other languages only have eval() - which takes a string and parses and executes it as code. In Lisp, eval() takes a Lisp list object and executes that.
For eg.
>> code: load "foreach n [1 2 3 4] [print n * 2]"
== [foreach n [1 2 3 4] [print n * 2]
]
>> type? code
== block!
>> do code
2
4
6
8