Home
Blog
Recent Posts
Updated
Dot Net Perls

When to Use List Comprehension in Python

Some features of Python are in nearly every guide, but are they are useful in practice? Consider the list comprehension syntax. It does a similar thing to the map built-in in most programs—it creates a new list from an existing iterable.

To be fair, list comprehension has some advantages over the map built-in. It can remove elements with an if-clause at the end. And it returns a list, not an iterable—with map, we would need to further call the list built-in to get a list.

But list comprehension can be worth avoiding because:

It leads to excessively complex syntax.
Other developers may be unfamiliar with the syntax and its quirks.
Other approaches, like for-loops and the map built-in, can accomplish the same sorts of tasks.

In my view, list comprehension is useful for creating lists with straightforward logic—like a list of 100 positive integers. But for complex things, or in cases where a function call is needed, other approaches like for-loops or map are a better choice. It is good to keep list comprehensions, should you decide to use them, fairly short and simple.

When to Use Rc and Arc in Rust

Suppose you (as a Rust developer) have built up a struct instance with some data—like the text of a file. Let's call this struct FileData. And you want to access this data in various functions in the program. Rc or Arc can be used for this purpose.

The program has a couple other structs that are used throughout—let's call them Info and InfoTwo. Many functions in the program have arguments of types Info and InfoTwo. We can put an Rc or Arc containing the FileData on these structs.

Though it is accessible from two structs (Info and InfoTwo) the FileData struct is only resident in memory once. It was never copied—just an Rc or Arc was copied, and this involves just an integer increment, and a small number of bytes. This is called reference counting.

If Info and InfoTwo are passed to different threads, we should place them in Arc—otherwise, we can just use Rc. In my experience, Arc is preferred as most Rust developers want to use threads, and Arc will work correctly on a single thread as well.

This Is My Favorite Java Feature

Though it is similar to languages like C#, Java has some unique features that help improve programs. One feature, the Optional class, indicates whether a value exists or not—it is a way to clarify logic in modern Java programs. I think it is a great feature.

Here's why—without Optional, we might use magic constants on a value like an Int to indicate that no value exists. But with Optional, we can just use Optional.empty and our logic is clearer. Optional in Java is similar to Option in Rust, and an equivalent feature in Swift.

When considering Optional, we should remember that:

It has a learning curve—we need to learn to call isPresent, isEmpty, and use other methods with lambda expressions.
It can cause exceptions in methods like get if used incorrectly.
It may impact performance in a negative way—it should not be used in some lower-level, performance critical code.

By storing an Optional int in a class, we indicate that the value may or may not exist. So every time we access the field, we must use methods on the Optional to get its inner value. Still, Optional is useful in clarifying when a field is valid—and it is one of my favorite Java features.

Visual Studio Code and C#

C# is a Microsoft product at its core, even though it is developed in an open-source way these days. It makes sense, then, that another Microsoft product, Visual Studio Code, has exceptional support for C#. I installed the C# language support in VS Code and tested it out.

With features like IntelliSense (this is the auto-completion logic where the editor guesses what you are going to type when you press period after a type name), VS Code offers many advantages over Notepad. I am not sure if they still call it IntelliSense, but it is helpful for serious developers.

Other features of VS Code with the official C# extension include:

Support for renaming types and variables (this is simple refactoring).
More advanced refactoring support, when you right-click on a something and go to Refactor.
Errors that appear directly in the code where they were triggered.
Syntax highlighting to make programs easier to read.

Overall I found the C# support in VS Code to be superior to that in other editors. One big drawback of VS Code is its reliance on Chromium to render its user interface, which makes it slower than programs like Zed. But other than the slight slowdown, it is both more compatible with languages and systems, and has more features, making Visual Studio Code a good choice for developers new and experienced alike.

Gemma3 4B Local LLM Review

About three months ago, Google released its open-weights Gemma 3 LLMs. These models can be downloaded and run on computers with enough RAM using the Ollama program. This is fine—but are the models worth bothering with?

To test, I downloaded the 4B models, as my Mac mini M1 with 8 GB of RAM cannot run anything larger than that. The gemma3 4B QAT (quantization-aware training) model has 4.3 billion parameters and can run on the unified 8 GB memory of the Mac mini M1. Not only this, but Ollama supports GPU-acceleration of the model, so it is fairly fast in responding.

I tested the default gemma3 4B quantized model, and the QAT model, and my findings are that:

Gemma3 4B QAT is indeed better at providing answers than the non-QAT model, so I would always recommend the QAT models (look for "qat" in the model name).
The 4B models show considerable perplexity—it is best to only ask the model questions that correspond to popular Google searches, as this is mostly what it seems trained to answer.
Gemma3 4B QAT generates about 15 tokens per second on the M1 chip and 8 GB of RAM.
On the Mac M1 with 8 GB RAM, the Gemma3 4B-IT-QAT model causes macOS to use about a gigabyte of swap memory, even when doing light web browsing.

Definitely prefer QAT—there are cases where the QAT models got the answer right, and the default model did not. Gemma3 has an enjoyable style, and it uses emoticons in its greetings. It is a friendly, and even useful, assistant—it is possible to use it with only 8 GB of RAM on a Mac, but 16 GB would allow faster operation of the computer without swapping.

GNU Image Manipulation Program

Sometimes it is necessary to give a program a beautiful and elegant name. In other cases it doesn't matter. For instance, the open-source image editor uses the name GNU Image Manipulation Program (GIMP). At least it is possible to figure out what the program is used for from its name.

Several years ago, I had a project that I used GIMP for on macOS, and it was difficult for me to figure out how to use it. It was frustrating. I came close to giving up, but I persisted, and I was able to finish the images required.

In 2025, a new version of GIMP has been released, and it seems to have some big improvements. It has a more intuitive interface that will be easier for newcomers to figure out. For the most part I have been pleased with GIMP 3, although I haven't done any complicated image editing yet. It does have some rough edges still, but for those who are not going to make monthly payments for a more powerful program, it is a great deal and highly recommended—GIMP 3 is a step forward.

When to Use Records in C#

Often when developing C# programs we have small classes that only have a couple fields or properties. For example, a Point may have just two fields—its coordinates. Do these types need an entire class, with a constructor? Or should we condense the logic and keep the program smaller?

With records, we can specify—in a single line—a class that has some fields. Each field has a type and a name. There are some limitations with records, however, so it is best to use them only when certain conditions are true. We can use records when a class:

Has no methods, properties, or custom constructors.
Has no complex inheritance issues (a derived class) and does not implement any interfaces.
Is unlikely to need any of the previously-mentioned features in the future.

Records, which are also available in Java, can define a class with different fields in a single line. They remind me of tuple classes in Rust as well. If I were developing a program in C# or Java, I would aspire to use records when adding types—this would help keep the code base smaller and easier to manage.

Should Interfaces Be Preferred in C#

There are some things about C# that are confusing, even for developers who have known the language for a while. For example, there are many ways to have a type share parts of itself with another type. We have inheritance, abstract classes, and interfaces.

When should we use a normal class, and then derive another class from it? And when should an abstract class be used? Interfaces meanwhile are not a class at all, but allow us to treat different classes as though they are the same, through the interface.

After working with languages that do not support inheritance at all, I suggest just using interfaces:

Interfaces allow us to unify 2 different types and share code that acts on those types through the interface.
Interfaces avoid complicated issues with base constructors.
Interfaces are used throughout the built-in types in .NET, so developers can figure out how to use them without much trouble.

I am not against using language features to improve program quality, but inheritance often seems to result in excess complexity—to understand one class, you need to understand all the base classes. Instead, with interfaces, our code is flatter and more local to the class. Class derivation can be useful, but in my view, interfaces usually are a better choice.

This Is My Least Favorite C# Feature

Usually C# is a pleasant language to work with—it makes logical sense and can accommodate fairly complex programs. But some features in the language are inconvenient or downright flawed. One feature I like to avoid is the Clone method.

Part of the ICloneable interface, the idea behind Clone is that we have this interface that we use to define how an object is cloned (duplicated). But the interface does not do that. It does not specify to what extent the object is cloned. Here are the problems:

Clone may copy just the top-level fields from the object, not any nested fields.
A developer may implement a clone that does "deep" copies if this is desired—there are no rules here.
Because some Clone calls may be shallow and some deep, we never really know what we are getting when we use Clone.

So ICloneable is supposed to give us a standard way to duplicate objects, but it just makes us more confused when we cannot figure out what the method does with regards to nested objects. It is a counterproductive interface—one that makes programs harder to use and more confusing. For the most part, it is best to avoid ICloneable and Clone altogether.

Viewing Article Links

Suppose a person ends up on Dot Net Perls, and this person is reading about how to use the List in C#. This is a great thing to do. But over time my List article, along with most of the other ones, has accumulated lots of links to other articles on this site.

From a certain perspective, this is good—someone might want to browse around and view related topics. But for someone who is focused on the List, it is probably better to get rid of distractions and only show the links if requested.

To this end, I have added a Links button that, when clicked, shows all the links on the page in a separate place at the top. I hope this helps makes the pages less confusing, and also makes it possible to browse the links and go to a different page if desired. Try it out—it works the same way as the zooming images feature.

More
Dot Net Perls is a collection of pages with code examples, which are updated to stay current. Programming is an art, and it can be learned from examples.
Donate to this site to help offset the costs of running the server. Sites like this will cease to exist if there is no financial support for them.
Sam Allen is passionate about computer languages, and he maintains 100% of the material available on this website. He hopes it makes the world a nicer place.
An RSS feed is available for this blog.
Home
Changes
© 2007-2025 Sam Allen