« first day (211 days earlier)      last day (2188 days later) » 

8:41 AM
@EliahKagan we got the same instructions it seems
 
Right.
There's no formal guarantee that they produce the same instructions, because there's no formal guarantee even that the same code produce the same instructions across separate builds (even with identical toolchains and configurations--for example, with the same version of GCC and all the tools it uses and the same command-line options passed to the g++ command). Also, I should note that the binary files are not identical because the symbols that are emitted, for use by linkers, are different.
...But the implementation of the functions comes out the same, which is entirely to be expected, and it's a good thing.
To be clear, we're both talking about how the version with function overloading and the version with a function template produced the same instructions as each other, right? In contrast, in each case, there are two actual functions, and those functions have different assembly instructions, because one of the functions multiplies ints and the other mutiplies doubles. (I just want to make sure we're on the same page.)
So, in a dynamically typed language with duck typing, like Ruby or Python, a function is automatically capable of handling arguments of all different types, provided that whatever objects are passed as arguments are capable of responding to the operations that are invoked on them. If called with arguments that can't do that, a runtime error occurs; if called with arguments that can but the operations are interpreted in a way that doesn't do what you want, you get a logic error (a runtime bug).
 
9:01 AM
@EliahKagan you wrote two programs, and they both have two functions called multiply, one for dealing with integers and one for dealing with doubles. You wrote the programs differently, but the compiler explorer showed that they produced the same instructions as each other. The instructions for the multiply function for integers came out the same from program 1 and program 2, and the instructions for the multiply function for doubles came out the same in program 1 and program 2
But the function for multiplying integers needed different instructions from those for multiplying doubles
 
Yes.
@EliahKagan For example, in Ruby, you can multiply an array of strings by a string. This joins the strings in the array given as the first operand to * into a single string, such that they are separated by the second operand to *. For example, %w[foo bar baz quux] * '__' (which can also be written ['foo', 'bar', 'baz', 'quux'], as %w in Ruby is like qw in Perl) evaluates to 'foo__bar__baz__quux'.
The elements of the array need not even be strings. Any non-string element has its string representation used. If you had a function that multiplied its operands -- and did other stuff, because who would write a function that just multiplied its operands when you can just use the * operator directly! :) -- and you ended up accidentally passing an array and a string, then it would do that.
 
@EliahKagan by "[provided that] arguments are capable of responding to the operations that are invoked on them", you mean that I can't write elephant/giraffe, because an elephant isn't capable of being divided by a giraffe (maybe a family of elephants could be divided by the machinations of a giraffe, but the interpreter won't be distracted by such silliness)?
@EliahKagan that's cool
 
@Zanna That's one way, yes. It could also just not be defined for that operation at all. For example, if one of the things a function does every time it is called is to invoke it's argument's foo method, and you pass something with no foo method, then that, too, will produce a runtime error. The corresponding logic-error case to that would be if you passed something that did have a foo method, but whose foo method didn't do the same thing as the intended arguments' foo methods.
@EliahKagan This is worse than immediately getting an error. Likely it would result in an error eventually, but it might be hard to figure out what caused it. In contrast, in C++, an extremely high volume of incomprehensible error messages from code far away from where the actual bug happens at compile time.
@Zanna I'm not sure which part you mean, but if you're talking about joining strings with *, then while I don't recommend refusing to use that syntax, I recommend keeping in mind that there is a join method that, at least some of the time, might make more sense later when you or someone else reads the source code (e.g., %w[foo bar baz quux].join('__') produces the same result as %w[foo bar baz quux] * '__').
In C++, the compiler produces multiple, separate implementations. So sometimes your program is bigger than you might think, just looking at the source code, if it uses templates heavily. Compilation can also take a long time. However, because the compiler generates separate functions, type checking is done completely during compile time, and information about the types of the template parameters doesn't have to be emitted into the executable code.
 
9:25 AM
@EliahKagan I meant it's cool that something potentially useful happens when you try to "multiply" two different things. But it seems like this might actually be a pain since, like you said, there won't be any errors at the point where those kinds of arguments accidentally get passed
I have to go afk for hours now but will read later. Thanks for educating :D
 
Also, the separate functions produced by instantiating the function template can be separately optimized. (C++ is all about usually being able to produce code that is reasonably fast while usually keeping the ability to work with abstractions. That is, the idea is that you can write that is high level but nonetheless performs well. There's a lot about C++ that is really excellent. The biggest downside of C++, I would say, is that is very complicated.)
A well-written template will often generate code that performs very well even when it is used later, by totally different developers, with types that didn't even exist when it was originally written. (The developers must have the template's source code for this, though.)
@Zanna K, ttyl. Btw, I am not trying to discourage you from learning Ruby! (Btw, I am also not trying to convince you to learn C++ or F#, though if you're interested in learning a statically typed compiled language, I have some ideas about what might interest you. These ideas are not C++ or F#. :)
 
10:28 AM
Momentarily on mobile
 
when I see my fresh 18.04 install, this is going to be a catastrophe
I'm in the first time in two years managed to mess up my Ubuntu install and installed 18.04 directly
because installing 17.10 now as a fix was not feasible
not for 26~~ days
 
I should mention that my interest in learning programming languages doesn't come from a pressing need to create software. I don't find it off-putting that confusing things might happen or that problems might be hard to find. That is even quite attractive, because difficult things might be fun
 
hehehe I'm a puzzler, this is why i learned to program, to solve problems
 
 
1 hour later…
11:44 AM
@Zanna As far as I know, confusing things and hard-to-find problems happen regularly with any programming language. So... you're in luck! :)
 
12:18 PM
Lol :)
 
12:53 PM
If you're interested in statically typed compiled languages, the language I was going to suggest was Kotlin. I don't actually know Kotlin at all. I tried it out a while ago, though, and was impressed. It supports the common styles of programming--procedural, object oriented, functional, generic--well.
Its most mature and popular implementation targets the Java VM (and Kotlin is designed largely for that), so many situations where you might consider Java or Scala are use cases for Kotlin, too. It was designed by developers at JetBrains, and it's supported by IDEA (their IDE).
Android Studio is currently based on IDEA, so it supports it too. Kotlin is fully and officially supported for developing Android apps. (This doesn't quite follow from it targeting the Java virtual machine, as Android uses a different virtual machine.)
Kotlin's type system is really nice. You don't dereference nulls unless you really try, because the type system makes information about whether or not a reference can be null available at compile time and uses it to enforce correctness.
There's a mechanism to explicitly force a nullable reference to be converted to a non-nullable reference (throwing an exception if that fails), but it's rarely necessary and--based on my brief try with the language--not even tempting to do that.
Kotlin has type inference, a compact syntax for declaring mutable variables (so that people will actually do it), and it fully support object-oriented programming whilst still not trying to force it down developers' throats.
Kotlin has local functions (you can write a function in a function) and lambda expressions, and they capture variables from the surrounding scope. This doesn't require the use of any extra, complicated syntax, and it allows you to modify the variables (unless they were declared immutable).
It has flow-sensitive typing ("smart casts"), which is to say that, in branches of code that are selected based on a dynamic determination of an object's type, that additional type information is reflected in the static type of expressions consisting of or otherwise containing the variable whose type was checked.
There are other languages with these features. There are even some with all of them (or that have features that are similar and just as good). However, I am not aware of any languages that have these features and support all the common styles of programming. Recent versions of C# have many of these features, but not all. I like C# better than Java, but if Kotlin had existed when I learned C# (it didn't), I would either have learned Kotlin instead or I would wish I had.
(I still like C# a lot. But Kotlin differs from C# in most of the ways I wish C# were different, which is perhaps why I am capable of exuding so much excitement about it, even though I don't know Kotlin at all, therefore you should take what I am saying about it with a great grain of salt.)
 
1:34 PM
To be clear, languages like Scala and F# don't prevent programming in non-functional styles. But they're designed to support functional programming specifically (especially F#, which is similar to OCaml). Kotlin is often described as a better Java. I agree with this. People usually mean that just positively, but I'd add that it does have some limitations that come from the Java virtual machine.
Unlike in Java, you don't have to distinguish between boxed and unboxed primitive types in your code in Kotlin. But there is still a performance penalty associated with boxing, and generic collections still don't support primitive types.
Generics are still not reified as they are in the .NET Framework and Mono (which C# and F# target), which is the main thing I like better about those languages than about any language that targets a current Java VM (though I have hopes for the future).
I should perhaps add that Scala has many of these benefits and it's quite possible to program in an object-oriented or procedural style with it, so my preference for Kotlin may be aesthetic or related to its greater similarity to C#. (There are some major advantages of Kotlin over Scala--Kotlin compiles fast--but as someone who so far does not even use the language, that's not one of the factors that affects my views of it.)
 
 
2 hours later…
3:25 PM
@Videonauth I totally relate :)
@EliahKagan thanks for the recommendation! I was definitely going to encourage you to to share your ideas about what statically typed compiled language I might enjoy learning when I got back
 

« first day (211 days earlier)      last day (2188 days later) »