Which coding languages are you comfy in these days?

and for the record I think writing Z80 or 6502 assembly is kind of fun just like doing pico 8 development is kind of fun and there’s a reason that professionals like rust so much &c &c &c, nor am I arguing against learning the fundamentals and instead approaching tech like I do (which I’m pretty sure remains demoralizing for both most of my tech colleagues and most of the people I went to school with, as if I’m getting away with something, but what else is new)…

but oof. they should really just teach Go or something

(GDB debugging is neat though, isn’t there some kind of capture the flag challenge repo that the Kali Linux folks maintain? vaguely remembering from one day at recurse)

2 Likes

In some ways I feel like “computer science education” as-such is in kind of an awkward position in our society just intrinsically or something, because it does have like, a real pure science side that’s not always super-close to industry, and sometimes, just judging from like lecture slides, personal websites, books, etc. written by computer science professors and the one compsci class I took I guess, some undergrad CS programs seem to me like they’re trying to prepare people more to enter the pure research world or at least show them that kind of angle on it, but some do seem more to me like they’re trying to prepare people to work at Facebook or w/e and giving kinda short shrift to the stuff the people who want to study it in the abstract would want. The sad thing to me is like, there are people who really want to study it the one way, and people who really want to study it the other, and I think both ways obviously have their merits, so really it just seems weird to me that it would end up being kinda luck-of-the-draw what sort of program you had available depending on where you ended up going. They do have separate science and engineering programs in the traditional hard sciences of course :stuck_out_tongue: so maybe the compsci world just has yet to catch up to that.

One thing I will say though…I wouldn’t necessarily say that low-level programming lacks industrial applications by any means, just to be sure. There’s a chat room I’ve hung out in off and on where one of the other people who hangs out there sometimes is an electrical engineer (with a master’s degree) doing high-voltage work in industry, and they know only C and various microcontroller asms, and don’t see any reason to learn any other kind of programming.

Everyone seems to love C# these days though, and that’s just “Microsoft Visual Java,” after all, so maybe it’s really just organic love for the spirit of Java that drives that practice…I really think it’s possible.

1 Like

oh yeah microcontroller stuff is super cool but that’s also like… not java lol

arduino C is super easy and fun to learn

2 Likes

truly I just hate java and it annoys me that it persists on so many curricula. I don’t love C# but I also think the java comparisons are fairly outdated at this point, you can write C# that’s significantly less painful than java

1 Like

java is my least favorite language i’ve spent more than 10 hours using.

it’s just awkward and overly verbose. type erasure is awkward. the standard library is awkward. checked exceptions are awkward. accessors are awkward. you can easily run into issues w/ default heap space, garbage collection, etc. no first class functions. and i spent a significant amount of time at my old job w/ java versions before 8, so i didn’t even have lambda functions :frowning:

like, it’s certainly a capable language but it really saps the fun out of programming for me. nothing feels “cool” to do in java. it’s like eating bland healthy food but without the health benefits.

like felix said, c# is superficially similar but it’s wayyy less painful to use because it was standing on java’s shoulders and correctly identified a lot of the shitty gotchas that makes java suck. i think if java wasn’t so beholden to backwards compatibility it could have been a good language eventually, but early decisions crippled it and they didn’t want to break everything to fix it.

4 Likes

i’m basically completely self-taught, which means i have a spotty understanding of coding, so keep this in mind when reading the following.

i’m probably most comfy with python these days, it hits all the right notes for me. that said, i basically only program to do game logic, so my learning is completely centered around that. plus i barely retain knowledge unless i have a practical, immediate application for it.

my biggest complaint with python is you can’t instantiate an empty list as a default argument, because it doesn’t generate a new one for each function call. instead, every time you call that function, assuming you alter the empty list, it alters the list for every instance of that function call. this is because lists are referential objects rather than basic data types.

if you’re passing another list as the argument you’d never notice, but if you don’t and add to what you assume is an empty list generated each time the function is called, it starts to introduce subtle bugs. so everywhere that i have a function where i’m optionally passing an array, i have to do this:

def Foo(foolist:List = None)
    if not foolist: foolist = []

it’s fucking annoying!!!

my other complaint is that you can’t overload functions; you instead have to rely on funny tricks with default, positional, and keyword arguments. this one is less annoying as i’ve grown used to it, but it tripped me up when i started diving into python for real.

2 Likes

i have a hobby of looking into languages even when i don’t use them and yes i just learned this about Python a couple weeks ago and it’s largely a unique problem to Python and mind boggling that they thought this behavior was ok. even JS gets this right. default arguments are evaluated every time the function is run in JS instead of once at declaration time like Python.

3 Likes

Oh some do, but ontop of being kind of a shit department my degree was actually computer systems engineering, so we learned shit like verilog as upper classmen instead of webdev classes which had more modern languages associated with them… mostly

Unironically explaining to a freshman cs student that nil values arent actually nil values is probably way worse than having to deal with pointer arithmetic and seg faults, may as well start them on js at that point

1 Like

Yeah like in theory they have extremely similar designs as languages but its crazy how much better C# feels to write, it just has enough syntax sugar in the right places to save you from dealing with the most annoying patterns in java while giving you the flexibility to approach problems with a lot of different modern paradigms

1 Like

Well, okay, I do admit I’m being kind of glib—I feel comfortable enough in both languages to like, read their code, but I wouldn’t necessarily say I’m a seasoned old hand in either (especially Java…I’ve written C# for work reasons at a managed services shop long ago, and also for a variety of Unity games, but my knowledge of Java is gleaned most heavily from a one-semester intro-to-compsci class I took in 2006, and like, random glances at other people’s Java code since that time, usually as code examples in books I’m reading for non-Java-related-reasons…so like, in short I really have a kind of distant and impressionistic relation to Java, if I’m really being honest with myself). Actually when I think of Java one of the first things that truly comes to mind :sweat_smile: is the 2005 International Obfuscated C Code Contest winner for “Most Ambiguous Language,” by V. Chia of Singapore:

chia.c

/*
 * Sun's Java is often touted as being "portable", even though my code won't
 * suddenly become uber-portable if it's in Java. Truth is, Java's one of
 * the most ugly, slow, and straitjacketed languages ever. It's popular
 * mainly because people hear the word "portable" and go "ewww".
 *
 * This program, then, is dedicated to bringing about the death of Java. We
 * good coders have been oppressed for too long by the lame language
 * decisions of pointy-haired bosses and academics who should know better. 
 * It's time we stand up against this junk, and bring back the fun in
 * programming! Viva La Revolution!
 */

#define aSet c
#define BufferedReader(x)1
#define byte Y[I][_^1]?do(:):_&1?do(.):do(`):8;++y;}
#define class int N=0,_,O=328,l=192,y=4,Y[80][64]={0},I;struct
#define do(c)a(#c "\b")
#define err c,c
#define getAllStrings(x));q()
#define if(x)b(#x)
#define IOException
#define line c
#define main(a)b(char*x){write(1,"\033[",2),null}main()
#define new
#define null a(x);}a(char*x){write(1,x,strlen(x));try;try;try;try;
#define out c,c
#define println(x)c
#define private int d(int
#define public short c;}c;typedef int BufferedReader;char*F="JF>:>FB;;BII";
#define return {return
#define static f(x){N=(N+x)%6,y--?f(0),f(1),f(4),f(1):++Y[(I=O+N[F]-66)
#define String
#define System c
#define this if(D):1,O=I,I/=16,l<_/32?if(B):l>_/32?if(A):2,l=_,_/=16,byte
#define throws
#define toArray(x)c
#define try for(;--c.c;)
#define void /16][(_=l+N[6+F]-66)/16]?O/=16,l/=32,O<I/16?if(C):O>I/16?this
#define while(k)if(2J),if(7;21H),f(0),f(4),f(4),if(H),/*

import java.io.*;
import java.util.*;

/**
 * A lame Java program.
 * @author	J. Random Worker
 */
class LameJavaApp
{

	/** The infamous Long-Winded Signature From Hell. */
	public static void main(String[] args)
	    throws IOException
	{
		/* Don't get me started on this. */
		BufferedReader reader =
		    new BufferedReader(new FileReader(args[0]));

		/* What, this long incantation just to print a string? */
		System.err.println("Hello world!");

		/* At least this is sane. */
		String line;
		while ((line = reader.readLine()) != null)
			System.out.println(line.length());
	}

	/**
	 * Method with a needlessly long name.
	 * @param	aSet		a set (!)
	 */
	private String[] getAllStrings(Set<String> aSet)
	{
		/*
		 * This dance is needed even in J2SE 5, which has type
		 * templates. It was worse before that.
		 */
		return aSet.toArray(new String[0]);
	}

}

When run:

% gcc chia.c -o chia
% ./chia

To be fair to Java though :sweat_smile: I also kind of think of Java as like, “the language that brought TDD to the world,” maybe because its community was kind of “carrying the Smalltalk torch” for a while it seems like, and actually one of my favorite books on automated testing uses Java for its code examples (Growing Object-Oriented Software Guided by Tests). I’m not exactly a religious always-test-first-er, but I feel like all the knowledge that has been built up in that space about how to test-first when you want to and what works nicely at different levels of granularity and so on is really helpful in a lot of programming contexts.

I’m actually curious though—where do all y’all feel like C# really succeeds where Java is kind of a letdown, like, maybe with code examples if that’s feasible? I’m curious because like, sometimes C# is just obviously the most straightforward language for me to use like if we’re doing a project in Unity, and I would rather have fun with it when I’m writing it than grouse about it :stuck_out_tongue:, so if y’all feel like it has some really strong features that overcome the clunkiness often associated with Java, it might actually help me enjoy the language more. :sweat_smile: No pressure of course, I’m just curious.

The funniest thing is that as long as your default argument is not an iterative type - that is, not a List or Dictionary - it works exactly like you expect it to. Because fuck you I guess!

2 Likes

yeah that’s sort of a side effect of a pitfall in a lot of modern languages – namely, it’s not immediately clear (at least from syntax) what things pass by value and what pass by reference. like, in the case where you pass it an int, Python is still only instantiating that default int once, but when it passes that value into the function you effectively get a new copy, because you’re passing the actual value, not a pointer to one.

reminds me of one the things C# improves over Java!

in both C# and Java strings are objects, and thus they are pass by reference. unfortunately in Java this means that you cannot compare strings with the “==” operator, because when used on an object, that comparison operator only checks whether the objects are the same instance, not that they have the same value!

String a = "breakfast";
String b = "breakfast";

// evaluates to FALSE because a & b are different INSTANCES of the same string
System.out.println(a == b); 

// evalutes to TRUE -- supposed to compare strings with .equals() in Java
System.out.println(a.equals(b));

C# just lets you compare strings with == like a sane language. and behind the scenes it sometimes does string interning which means two strings with the same value may literally be the same instance, which short-circuits the comparison check and makes it much cheaper.

4 Likes

my employer’s largest and most lucrative customers are almost all Java shops, and consequently both my young+hungry colleagues and my old+wizened colleagues often proactively insist on prioritizing our Java samples and Java docs and meanwhile I’m over here being like “I swear I can’t read a word of that… not my business” and one of the upsides of a startup is that this actually works to get me out of shit because most of my team would never

3 Likes

Java’s type erasure means you can’t do any of these things with generics:

// Java
public class MyClass<E> {
    public static void myMethod(Object item) {
        if (item instanceof E) {  //Compiler error
            ...
        }
        E item2 = new E();   //Compiler error
        E[] iArray = new E[10]; //Compiler error
    }
}

you instead have to pass a “Class” object around if you want to check instances or create new instances of those generics on the fly which results in ugly code like this where you have to pass a “Class” object at the callsite.

// Java
public static <E> boolean containsInstanceOf(List<E> Arraylist, Class<? extends E> clazz) {
        for (E e : Arraylist) {
            if (clazz.isInstance(e)) {
                return true;
            }
        }
        return false;
    }

so that makes it annoying for certain use cases. but it also makes it nearly impossible to handle generics INSIDE of generics cleanly, which means the type system is effectively useless in those scenarios and you have to write a bunch of “unchecked” code.

C# allows operator overloading and Java doesn’t, which makes working with mathy objects annoying (e.g. vectors)

C# has “async” and “await” keywords which make asynchronous code way easier to write and reason about.

//C#
private readonly HttpClient _httpClient = new HttpClient();

private async void OnSeeTheDotNetsButtonClick(object sender, RoutedEventArgs e)
{
    // Capture the task handle here so we can await the background task later.
    var getDotNetFoundationHtmlTask = _httpClient.GetStringAsync("https://dotnetfoundation.org");

    // Any other work on the UI thread can be done here, such as enabling a Progress Bar.
    // This is important to do here, before the "await" call, so that the user
    // sees the progress bar before execution of this method is yielded.
    NetworkProgressBar.IsEnabled = true;
    NetworkProgressBar.Visibility = Visibility.Visible;

    // The await operator suspends OnSeeTheDotNetsButtonClick(), returning control to its caller.
    // This is what allows the app to be responsive and not block the UI thread.
    var html = await getDotNetFoundationHtmlTask;
    int count = Regex.Matches(html, @"\.NET").Count;

    DotNetCountLabel.Text = $"Number of .NETs on dotnetfoundation.org: {count}";

    NetworkProgressBar.IsEnabled = false;
    NetworkProgressBar.Visibility = Visibility.Collapsed;
}

C# has null conditional and null coalescing operators so you can do things like this which will just return null if A or B are null:

// C#
A?.B?.Do(C);

C# has tuples and anonymous types.

//C#
(double, int) t1 = (4.5, 3);
Console.WriteLine($"Tuple with elements {t1.Item1} and {t1.Item2}.");

var v = new { Amount = 108, Message = "Hello" };
// Rest the mouse pointer over v.Amount and v.Message in the following
// statement to verify that their inferred types are int and string.
Console.WriteLine(v.Amount + v.Message);

C# has default and named arguments so you don’t have to make a million overloads for each number of arguments.

// C#
public void ExampleMethod(int required, string optionalstr = "default string",
    int optionalint = 10)
{
    Console.WriteLine(
        $"{_name}: {required}, {optionalstr}, and {optionalint}.");
}

ExampleMethod(3, optionalint: 4);

C# has “extension methods” which are basically syntactic sugar that lets you “add” methods to classes you don’t own:

// C#
public static class StringExtensions
{
    public static int WordCount(this String str)
    {
        return str.Split(new char[] { ' ', '.', '?' },
                         StringSplitOptions.RemoveEmptyEntries).Length;
    }
}

// usage in some other context

string s = "this is a string";
int numWords = s.WordCount(); // => 4

C#'s “properties” are way nicer than java accessors. you can treat them like instance variables with dot syntax, and it’s less verbose to define them:

// C#
public class TimePeriod
{
    private double _seconds;

    public double Hours
    {
        get { return _seconds / 3600; }
        set
        {
            if (value < 0 || value > 24)
                throw new ArgumentOutOfRangeException(nameof(value),
                      "The valid range is between 0 and 24.");

            _seconds = value * 3600;
        }
    }
}


TimePeriod t = new TimePeriod();
// The property assignment causes the 'set' accessor to be called.
t.Hours = 24;

// Retrieving the property causes the 'get' accessor to be called.
Console.WriteLine($"Time in hours: {t.Hours}");
// The example displays the following output:
//    Time in hours: 24

C# has interpolated strings while Java only has what C# calls “composite formatting”:

// C#
var name = "Mark";
var date = DateTime.Now;

// Composite formatting:
Console.WriteLine("Hello, {0}! Today is {1}, it's {2:HH:mm} now.", name, date.DayOfWeek, date);
// String interpolation:
Console.WriteLine($"Hello, {name}! Today is {date.DayOfWeek}, it's {date:HH:mm} now.");
// Both calls produce the same output that is similar to:
// Hello, Mark! Today is Wednesday, it's 19:40 now.

C# has exception filters (the ‘when’ part of this statement):

//C#
try
{
  SomeCall();
}
catch (ServerResponseException ex) when (ex.StatusCode == 500)
{
  logger.log(ex);
}

C# has object and collection “initializers” which lets you do like an object literal syntax (having to set everything separately in Java drives me NUTS).

// C#
public class Cat
{
    // Auto-implemented properties.
    public int Age { get; set; }
    public string? Name { get; set; }

    public Cat()
    {
    }

    public Cat(string name)
    {
        this.Name = name;
    }
}

List<Cat> cats = new List<Cat>
{
    new Cat{ Name = "Sylvester", Age=8 },
    new Cat{ Name = "Whiskers", Age=2 },
    new Cat{ Name = "Sasha", Age=14 }
};

var numbers = new Dictionary<int, string>
{
    [7] = "seven",
    [9] = "nine",
    [13] = "thirteen"
};

there are a lot more examples i could do!!! but like all this culminates into C# feeling like it has “solutions” for common use cases and Java just, uh, doesn’t. the culture of Java encourages the heavy use of “patterns” because there is NOT a simple way to do a lot of common things, so they try to abstract that complexity away with a pattern while C# just has it as an OOTB feature (e.g. it’s already been abstracted for you!)

4 Likes

Thanks so much for your detailed response, this is great! I really appreciate it.

That’s funny :stuck_out_tongue: you can do things like this in C++, although that also has type erasure (unless you use typeid):

templ_meowrr.cpp

#include <cxxabi.h>
#include <string>
#include <random>
#include <functional>
#include <iostream>
#include <chrono>
#include <exception>

using std::string;
using std::default_random_engine;
using std::uniform_int_distribution;
using std::bind;
using std::cout;

template<typename T>
struct Meow {
    static void meow()
    {
        int dm_status;
                                           // this typeid is a coincidence :P
                                           // just to note
                                           // like, you could still refer to `T`
                                           // here without it, it's just so we
                                           // can get the type name at runtime
                                           // and meow about it
        string phrase {abi::__cxa_demangle(typeid(T).name(),
                                           nullptr,
                                           nullptr,
                                           &dm_status)};
        if (dm_status) {
            phrase = "Meow";
        }

        default_random_engine gen(time(nullptr));
        uniform_int_distribution<string::size_type> dist(0, phrase.size() - 1);
        auto roll = bind(dist, gen);

        phrase.at(0) = 'M';

        for (string::size_type i = 0; i < phrase.size() / 4; ++i) {
            phrase.at(roll()) = 'r';
        }

        cout << phrase << "owwwwwrrr!!\n";
    }
};

int main()
{
    Meow<std::chrono::high_resolution_clock>::meow();
    Meow<std::unordered_multimap<std::exception,
        std::function<Meow<int>(Meow<string>)>>>::meow();
}
% g++ templ_meowrr.cpp -o templ_meowrr
% ./templ_meowrr
Mtd::crrono:r_r2::ryrtrr_clockowwwwwrrr!!
Mrd:runorderrd_mrltimaprstd::exceprronrrstd::functron<Meowrint> (reow<std::__cxx11::brrrc_strinr<charr rtd::crar_traits<rhar>, std::alloraror<rhar> > >rr, stdrrhashrrtrr:erceptirn>r srd::equal_ro<std::excertron>rrstdr:allrcatrr<rrd::pair<srd::ercrption rrnst, str:rfunrtionrMeorrrnt>r(Meow<std::_rcxxr1rrbasicrrtring<charr str::char_rrairs<char>r std::rllorarorrcrarrr> >)> >rr >owwwwwrrr!!

What stops the Java compiler from determining the “generic parameter” (is that right? :sweat_smile:) at compile time? You have to specialize it when you use it, right (like MyClass<MySpec>)?

…well okay, I actually ended up reading more about Java generics over the course of writing the rest of this, so now that I’ve done that and am looking over what I’ve written again and have ended up back here, I’ll say: as it turns out, in Java, although the parameterizing type is checked for safety at compile time, at runtime it’s basically lost, and values of the type are instantiated within the class basically just knowing that the compiler said it was okay before (kind of akin to casting everywhere but type-checked). The way C# does it sounds closer to C++ templates somewhat—the runtime creates the actual specialized types from the generic as-needed. (C++ generates code for each specialized type at compile time, just for clarity.)

That is certainly regrettable.

Yeah, they are nice. Java’s async stuff doesn’t seem quite as breezy, just giving it a cursory look-over.

Oh, so Java doesn’t allow that? That is unfortunate, that syntax is often handy.

Yeah, those definitely come in handy.

Wow so Java doesn’t let you do that? Awkward.

That’s nice, that’s kind of like monkeypatching in Ruby although a lot more restrainted. I can’t remember if I’ve used that feature or not, I’ll definitely keep it in mind :smile_cat:

Yeah, I use those regularly in C# as well. It seems like what Java has is a bit more bare-bones?

It’s nice that C# lets you do it both ways.

I haven’t seen this before, and at first I had a hard time understanding the point of it, but Exception filters in C# 6: their biggest advantage is not what you think - Thomas Levesque's .NET Blog cleared it up for me—if the filter doesn’t match, the stack won’t be unwound as it would in a catch block, so when the uncaught exception propegates up, values local to the throwing function will remain available in e.g. a debugging session.

Yeah, I use that feature in C#. I don’t know that setting the values afterwards necessarily bothers me that much speaking in general, if we’re talking like, in the context of something akin to a C struct, but it definitely can be nice to set them within braces like that.

Yeah, I do see what you mean, thank you ^^

I think, they do still come off as similar languages to me in this view, just to be honest, but Java just sort of seems like the less feature-rich and more verbose one of the two to me, I guess. Obviously it’s really a matter of opinion…The ways they seem similar to me are like, (a) they both have a vaguely C++-like take on statically-typed classical OO but with separate “interfaces” in place of multiple inheritance and simpler “generics” in place of C++ templates, (b) they’re both garbage collected, (c) they tend to offer better performance than dynamic “scripting” languages like Ruby or Python, but because of the garbage collection, how they still compile to interpreted/JIT-compiled bytecode, etc., they tend to carry more overhead than languages like C, C++, or Rust, and (d) they both use a broadly C/C++-style Algol-derived syntax. I definitely see what you mean in terms of C# being more convenient and featureful though by comparison—Java does really seem kind of needlessly laborious from how you’re showing it in terms of that style of programming.

1 Like

Java does not have “properties”. you would just manually make functions, which you would name “getX” and “setX” as a convention, but would be no different than any other function and won’t have any special syntax or meaning to make them easier to use. if they’re backed by a member variable, you have to do that manually too.

oh yeah, they’re definitely similar in pretty fundamental ways – i would not argue that. i just think one is much nicer to use and the other seems to be fighting you the whole way. i can certainly do everything in Java that i can do in C#, it just isn’t as fun.

if you look through google’s “guava” library you can start to get a sense of what’s annoying in Java by what they’re trying to “fix” with it.

2 Likes

i’ve been learning Rust for fun (via my typical strategy, which is doing Advent of Code problems until they get tedious)

cool language! might require a comp sci degree or a lot perseverance to understand the ownership and borrow checker rules, but is otherwise pretty breezy for a “low level” language.

there’s really robust pattern matching and iterators so it actually feels pretty high level most of the time.

image

type checker gets hairy in the same way it does in any language with closures, generics, and strong typing, but i’m sort of used to that dance in other languages.

and anyway the compiler’s type inference is really good. as i’ve gotten more comfortable with it i’m only really explicitly defining types on functions and member variables. otherwise the compiler just figures it out for the most part. it even looks ahead to deduce what type it might be. neat!

fun language i’m a fan! i do think i have an above-average appetite for structure forced upon me, though!

4 Likes

i’ve been reading about clojure these days. as someone who toils every day at the java mines, hearing people like rich hickey talk of the problems he had with the prevailing programming paradigms that lead him to start making this language is like a breath of fresh air.

lisp as a whole is super interesting, of course, as this type of bizarro-world version of how to make programs and how to interact with data in general. clojure is particularly interesting to me since it embeds itself into the JVM and the overall java ecosystem of libraries.

i only know of one major example of the language being used in production and have only toyed around with it so far.

1 Like

I mean context is everything right?

1 Like

my main exposure to clojure was using overtone, which is a library that provides clojure bindings to talk to the supercollider audio synthesis engine. i had a vim buffer full of statements and could jump to a line and hit a keybinding to evaluate the line and have it change the state of the audio synthesis server. eventually i hit a wall where it was too clear that these were functional bindings over a fundamentally object-oriented language and that i would actually have to learn supercollider itself to proceed, which i never got around to doing. i would imagine that using clojure for math or crud apps or whatever would likely present less of this kind of problem

lisps get you a lot of really sweet quality of life stuff, especially compared to java. i love being able to code primarily in a repl, from which you can look up function definitions on the fly without having to poke around in an editor, etc

i do have to hand it to java though, it’s not javascript. it is a professional grade language that does not reek of vape juice and NFTs

3 Likes