I've often been asked for suggestions for an appropriate first project in Rust, and I think that writing a version of a unix utility is a great choice, for a bunch of reasons!
There is a diverse and colorful cast of characters to choose from that all provide an appropriate scope and difficulty level, such as:
tree: Print a graphical representation tree in visual form
strings: Extract plaintext strings from binary files
wc: Count the lines, characters, and bytes in a file
ls: List the contents of a directory
nc: Read and write bytes to network sockets
cal: Print a cute text calendar
cat: Copy streams to stdout
cut: Extract delimited fields from linewise text records
sort: Sort lines
uniq: Print only unique lines
The existing implementation provided by your system serves as a specification, giving you an idea of how the tool works and whether or not your implementation has the same behavior.
The core functionality of these utilities is very simple, allowing a learner to quickly build something useful. And, many have additional features, allowing a learner to add and build if they wish.
ls is simple, but
ls -l is quite the project!
Many creative additions are possible, like colorful output, expressive configuration, and fun and useful new features.
IO and error handling are often front-and-center when writing these utilities, which provides a great chance to get used to explicit error handling.
structopt makes argument parsing a breeze. And, by leveraging the type system and custom-derive, it provides a nice example of a situation where Rust has enormous advantages over other languages, allowing you to do more with less code.
Rust binaries are fast to load and run, so performance is on par with native C implementations, and often much better than implementations in slower languages.
Rust binaries are self-contained, so packaging and distribution is manageable, so you can share your work with the world.
It's fun to use utilities that you wrote in your day-to-day workflow!
There are lots of fabulous examples of utilities in the rust ecosystem, like ripgrep, fd, bat, exa, and hexyl. (Damn, David Peter is a beast.)
If you're teaching others, a simple utility like
strings makes for a great demonstration of the basics of the language.
I think whether you start with the book or a project like this depends on the learner.
I much prefer to jump in and struggle mightily, so I started with a project like this (what eventually became just), but I think a lot of people might prefer to start with the book, or at least parts of the book.
A Kademlia-inspired modification of Dandelion for use in Grin.
On boot and restart, Grin nodes pick a random 256-bit node id which is broadcast to their peers.
Upon receiving a block, a new epoch begins if
block_height % 10 == 0. The epoch id is the 256-bit blake2b hash of the block hash of the block that started the epoch. (I.E. the double blake2b hash of the block header.)
At the start of each epoch, every node:
Calculates the relay weight of itself and all peers using the formula:
relay_weight = peer_id xor epoch_id. Relay weight is interpreted as a 256 bit unsigned integer.
Selects the node among itself and all peers with the highest relay weight as the relay target.
Determines that it is in stem mode if the relay target is a peer, and in fluff mode if the relay target is itself.
Then, for every stem transaction received:
If it is in stem mode, it immediately relays it to its relay target.
If it is in fluff mode, it aggregates transactions until its next patience timer expires, then broadcast them.
"Heavy" peers will naturally be chosen for relay targets, creating agreed-upon stem paths and fluff sinks, and leading to more opportunities for transaction aggregation.
In a well-connected network, one node may be the sink for all transactions during a given epoch, and thus see all unaggregated transactions during the epoch. It may thus be desirable to stick to random mode selection as in Dandelion++, so as to break up stem paths with randomly selected fluff sinks.
If block hashes are used directly as the epoch ID, peers could select peer IDs with a large number of leading 1s, thus biasing relay target selection towards themselves. Thus, we take the double blake2b hash of the block header as the epoch ID.
Since the epoch ID is known by all, a node could pick node IDs that had high relay weight during that epoch. To provent this, if a node connects to a new peer it should use a randomly assigned peer ID for the current epoch.
Should this modification be called Kademlion, or Objective-Dandelion?
Thanks to Antioch Peverell for the clear description of Dandelion++ whose language I shamelessly copied.
We all stood, gathered our things, walked down the cafe stairs and out to the dark and bustling Berlin street.
After a few goodbyes and handshakes, everyone headed off in different directions, for different destinations.
The meeting had felt momentous to me, a marker of strange and interesting times to come. I headed to the U-Bahn, alone.
Rustup is the rust toolchain manager. It can install Rust and keep it up-to-date.
Visual Studio Code is easy to use and has great Rust integration.
The Rust Book is a comprehensive guide to the entire language.
The Rust Playground allows you to quickly try out and share code snippets.
Rustlings are bite-sized exercises for learning rust.
The Rust-Lang discord instance is a great place to chat about rust.
I woke up last night after only a few hours of sleep, sweaty and disoriented.
Maybe it was miasmatic vapors rising up from beneath South of Market streets. Maybe it was the widening gyre opening up under the world. Maybe it was nothing at all. I don't know.
It felt like the world had ended, but I was still there. And the lights of the city glimmered through the window, so, it was still there too.
Lighting Network payment channels could be established between users and exchanges to speed the transfer of funds.
This would be a huge boon, moving many on-chain deposit and withdrawal transactions off-chain, but is possibly only the beginning.
Since Lightning Network payments can span different blockchains, an exchange could use a cross-chain Lightning node to expose its internal order book to external entities.
As an example, imagine that an exchange has an LTC/BTC trading pair and wants to allow non-exchange users to fill the orders in their order book.
The exchange runs a lightning node with a BTC channel and an LTC channel:
x: exchange node
a: third party node
b: third party node
<->: payment channel
a <---> x <---> b
The exchange dynamically sets the exchange rates across the channels based on their current best bid, best ask, and fee schedule.
With a best ask of 0.6 and a 1% fee, the exchange sets the BTC→LTC exchange rate like so:
a ----> x ----> b
When a payment is routed across the channels in this direction, LTC sell orders are filled.
With a best bid of 0.4 and a 1% fee, the exchange sets the exchange rate on the channel in the LTC→BTC direction like so:
a <---- x <---- b
A payment routed in this direction fills LTC buy orders.
In this way, exchanges can expose their internal order book externally and trustlessly. Anyone who wishes to make cross-chain Lightning Network payments will discover and travel over these routes with no special effort required by the exchange, assuming that their rates are competitive. Also, it’s likely that third parties will appear whose sole purpose is to search the Lightning Network for arbitrage loops and travel them until they are exhausted, thus bridging multiple exchanges when their order books cross.
IOTA is a cryptocurrency targeting the internet of things. It purports to be scalable, decentralized, and feeless. Unfortunately it is none of those things.
In this article I attempt to summarize the numerous technical, social, and ethical problems surrounding the IOTA project, The IOTA Foundation, and the IOTA developers.
VXX is a dangerous chimeric creature; it is structured like a bond, trades like a stock, follows VIX futures and decays like an option. Handle with care.
And, currently being algo traded by a program written in Excel VBA.
Strange times indeed.
Investing in cryptocurrencies is not the same as buying simple equity in a company.
Although each company has a different business model, they and the equity they issue are largely structurally homogeneous. They hold their monies in banks, pay for their expenses with wire transfers and cheques, follow prescribed rules of accounting, and issue stock that operates according to well understood rules. This is not to say that said practices are good or bad. They are simply a known factor.
Cryptocurrencies and tokens, however, are structurally heterogeneous. They have different codebases, modes of operation, levels of complexity, and security models. Although broadly lumped into the same category, they can, by the nature of these differences, have almost nothing in common.
Investing in one is like buying stock in a company with novel business models, banking practices, and accounting methods, and furthermore whose stock is issued under a bespoke scheme and follows unique trading rules.
Accordingly, a much, much greater level of care is required when making such investments. If any one of these novel mechanisms fail, your investment may go up in billowing smoke and flames overnight.
This is not to say that you should completely avoid cryptocurrencies and tokens, just, you know, do your homework.
I only program in PL/I because I'm BASED.
Programs first crawled from the murky oceans as simple lists of instructions that executed in sequence. From these humble beginnings they have since evolved an astonishing number of ways of delinearizing.
In fact, most programming paradigms simply amount to different ways to transform a linear source file into a program with nonlinear behavior.
- gotos that unconditionally jump to another point in the program
- an abort instruction that stops the program at some point other than the end
- a macro facility that substitutes one instruction for one or more other instructions
- a source file concatenation facility that concatenates multiple source files
- an include directive that is substituted for the contents of a source file
- structured repetition and selection, a la for, while, if, and switch
- subroutines and functions
- array oriented programming that replace explicit repetition with implicit repetition
- first class functions which delegation of behavior to the caller
- object oriented programming with dynamic dispatch, which allow the runtime type of an object to determine which instructions to execute
- aspect oriented programming, pattern matching against the structure of the call stack to execute instructions when functions are called or return
- event driven programming, executing instructions in response to external events
- declarative programming, which essentially delegates execution of one program to another
Parse structure from the languageless void.
This is pretty nuts. I was poking around in the storage area of my house, and I found a huge cardboard box filled with letters and audio cassettes and dust. Everything was Danish, German, and English, but mostly Danish. The name Max Rasmussen was everywhere, so I think it was all his stuff. I had to get a tape player at best buy to play the tapes, but surprisingly, they all played fine. One of them was an interview, in English, between Max and a man named Hans. I listened to it a few times, and I don't even know what to say. It's transcribed below.
"Well," he began, moving closer to her, "declarative programming is when you tell the computer what you want, and then the computer figures out how to get it. Pretty sweet, huh?"
"What kinds of things can you tell the computer you want?" she asked excitedly, her cheeks beginning to flush.
He thought for a moment, and began stroking her hair gently. "All kinds of things. There's a language called prolog you can use to ask about logical relationships. In SQL you can ask questions about huge quantities of data. With a program like bison you can declaratively describe a language, letting bison generate a program that recognizes it."
"Oh," she said breathlessly, leaning her head on his shoulder, "so I don't have to worry about choosing an algorithm--the computer will pick one for me?"