Comments by "xybersurfer" (@xybersurfer) on "ThePrimeTime"
channel.
-
208
-
162
-
75
-
19
-
13
-
11
-
7
-
6
-
6
-
5
-
4
-
4
-
4
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
3
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
maybe. although Zig, Java, C, assembly are all Imperative (stepwise).
you might want to try a Functional programming language. that was a huge eye opener for me. especially:
- lambda calculus / higher-order functions (declaring and using a function on the same line feels natural)
- typically way less lines of code needed than
- recursion (languages with tail call optimization are great, as they allow for endless recursion without blowing the stack)
- how in theory each call is an expression that fits on 1 line that can be rewritten on the next line (like maths)
- and how (usually) avoiding a global mutable state makes things more predictable
- pipe operator
- usually these languages have good type checking, in their compiler (the statically typed ones)
- and a few more topics (not that many)
it basically taught me that being productive, is a more interesting challenge than trying to go more low level. i'm mostly familiar with F# because it comes with .NET and Visual Studio Community (nice debugger) and i'm also a little bit familiar with Haskell.
SQL queries (as discussed in this video) was also an eye opener for me, as it's queries are in a Declarative langage. which means that in theory you don't have to explain to the computer how to do something, but just what you want done (which is kind of unique). although this only works in a database (maybe things like LINQ-to-Objects in .NET are an exception that allow you to "query" your program's data structures), it's still useful because a database is at the center of many applications.
speaking of databases, designing a database with an ER diagram was another eye opener for me, as it taught how data is organized in a simple and intuitive way (instead of trying to remember the all the normal forms). it taught me to quickly recognize design mistakes in databases. i love tools that allow me to draw a database and automatically generate the SQL commands that create it (my favorite is DeZign by Datanamic, but there are many others).
Zig looks interesting too. haven't tried it myself, but i do see similarities to C which i am familiar with. i think assembly is interesting to see a few times to get an idea of how it typically works, but the problem is that it's not portable like higher/more-abstract languages like everything you listed and functional programming. it really depends on what you want to do though. i'm not self taught like you though, so good job on that.
sorry for the long reply. programming is just a really interesting topic, and i didn't want to leave anything out.
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
2
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
@justgame5508 yes, there are typical circumstances that a program can't or shouldn't recover from, but this is ultimately dependent on the program. it's even dependent on the calling function. yes, invalid user input is recoverable when you use it in a form because the user can simply try again, but invalid user input in an unattended background job is usually not recoverable. failing to read from IO due to insufficient privileges is recoverable, in the rare case that you can read from other IO. as you said, it depends on the context.
the caller is the context. this becomes very obvious when writing a library. for me Exceptions are simply an easy way to end the control flow, when i can't fulfill what the caller asked. the caller can decide whether it wants to recover, by catching the Exception. my claim is that errors, are not recoverable in most contexts. so the caller doesn't have to do anything to let the Exception propagate by default. this saves a lot of (forgotten) error handling logic and magic return values (potential bugs) throughout the call stack, and that is the big advantage.
also dealing with invalid user input in a form is a bit of a special case because it often involves gathering all the errors to show to the user and not immediately ending the control flow. but if i don't yet want to end the control flow when encountering an error then i simply won't throw an Exception, until i've gathered the errors. personally, i usually only use Exceptions for the individual errors when the code is used in other place that need that. i think it's the job of languages and frameworks to make this less awkward and more performant.
unfortunately a lot of times languages and frameworks make the decision for you, that you should be using Error Values instead of Exceptions. but that's a separate matter.
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
@justgame5508 yes, there are typical circumstances that a program can't or shouldn't recover from, but this is ultimately dependent on the program. it's even dependent on the calling function. yes, invalid user input is recoverable when you use it in a form because the user can simply try again, but invalid user input in an unattended background job is usually not recoverable. failing to read from IO due to insufficient privileges is recoverable, in the rare case that you can read from other IO. as you said, it depends on the context.
the caller is the context. this becomes very obvious when writing a library. for me Exceptions are simply an easy way to end the control flow, when i can't fulfill what the caller asked. the caller can decide whether it wants to recover, by catching the Exception.
my claim is that errors, are not recoverable in most contexts. so the caller doesn't have to do anything to let the Exception propagate by default. this saves a lot of (forgotten) error handling logic and magic return values (potential bugs) throughout the call stack, and that is the big advantage.
also dealing with invalid user input in a form is a bit of a special case because it often involves gathering all the errors to show to the user and not immediately ending the control flow. but if i don't yet want to end the control flow when encountering an error then i simply won't throw an Exception, until i've gathered the errors. personally, i usually only use Exceptions for the individual errors when the code is used in other place that need that. i think it's the job of languages and frameworks to make this less awkward and more performant.
unfortunately a lot of times languages and frameworks make the decision for you, that you should be using Error Values instead of Exceptions. but that's a separate matter.
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
@darkenlightmage the strength of dynamic typing like in JavaScript i would say, is that you don't have to sometimes jump through hoops for the compiler, when the designers of for example C# didn't consider something. but i think this is rare enough, and the benefits of static typing are still a greater time saver. what do you consider to be the strengths of dynamic typing?
TypeScript tries to bolt on static typing, to fix JavaScript, but it does not go far enough in my opinion (because of having to be backwards compatible). there are also frequently issues in obtaining the right TS type definitions for the right version of existing JS libraries. this problem would not have existed if JS required types to begin with (Python seems to have similar issues with type hints). the "this" keyword is another mistake in JS. you can avoid it for yourself, but because using "this" is a mainstream practice, libraries expect you to use it. you basically can't fix the damage that has been done to the ecosystem by yourself.
Visual Studio constantly crashing seems like a rare problem, that i don't share. what i have encountered is that it seems to get slower with each version, but not enough for me to use a less suitable tool like VS Code for .NET development (which sounds insane to me). i suggest reporting the Visual Studio constantly crashing issue, to Microsoft if you still encounter it, so that it gets fixed.
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
@AG-ur1lj "Changing some value until some condition is met" changing stuff is pretty much a side effect, so yeah that's trickier to reason about but it's not because of recursion.
you can make recursion look just like a loop if you pass on to the next call, what you would pass on to the next loop iteration. so it's not necessarily harder to reason about.
but i get that syntax wise it would require creating a whole new function (i know that feeling in most languages). in functional programming languages you get away with this, because the syntax for creating a recursive function is about as heavy as writing a loop (only slightly heavier).
loops are only a subset of what you can do with recursion. typically it's problems that work with trees that are easier with recursion. but lots of things are trees. like finding an employee's highest level manager by going through the manager's manager etc, or problems like adding 1 to every node in a tree. XML is also an example of a tree.
but even in functional programming people try avoid dropping to recursion: most things, can be done with just a function call, because function definitions are values an so can be passed in and returned as values like in JavaScript (a.k.a. Higher Order functions). but also because a function call with missing parameters, results in a new function that expects the missing parameters (a.k.a. Lambda Calculus). so you get a lot of one liners like in this video.
side effects (including global mutable state) are typically avoided in functional programming. you still need them to change the outside world, but they are typically confined to only a few parts of your program, and make the rest easier to reason about.
bugs can still occur of course in functional programming, but a strict type system and the increased simplicity of the code makes it less likely (the whole program is basically 1 expression instead a statement like in most other Imperative programming languages).
TLDR: basically it helps if the language is flexible enough to not have to write out recursion, every time you need it.
1
-
@AG-ur1lj "Changing some value until some condition is met" changing stuff is pretty much a side effect, so yeah that's trickier to reason about but it's not because of recursion.
you can make recursion look just like a loop if you pass on to the next call, what you would pass on to the next loop iteration. so it's not necessarily harder to reason about.
but i get that syntax wise it would require creating a whole new function (i know that feeling in most languages). in functional programming languages you get away with this, because the syntax for creating a recursive function is about as heavy as writing a loop (only slightly heavier).
loops are only a subset of what you can do with recursion. typically it's problems that work with trees that are easier with recursion. but lots of things are trees. like finding an employee's highest level manager by going through the manager's manager etc, or problems like adding 1 to every node in a tree. XML is also an example of a tree.
but even in functional programming people try avoid dropping to recursion: most things, can be done with just a function call, because function definitions are values an so can be passed in and returned as values like in JavaScript (aka Higher Order functions). but also because a function call with missing parameters, results in a new function that expects the missing parameters (aka Lambda Calculus). so you get a lot of one liners like in this video.
side effects (including global mutable state) are typically avoided in functional programming. you still need them to change the outside world, but they are typically confined to only a few parts of your program, and make the rest easier to reason about.
bugs can still occur of course in functional programming, but a strict type system and the increased simplicity of the code makes it less likely (the whole program is basically 1 expression instead a statement like in most other Imperative programming languages).
TLDR: basically it helps if the language is flexible enough to not have to write out recursion, every time you need it.
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1
-
1