Here are the colorschemes that I like and use:
- Comments-only colorscheme for Sublime Text
- Acme colorscheme for VS Code
- Quiet colorscheme for neovim. Included by default.
Here are the colorschemes that I like and use:
We all use nvl. It’s so common and easy(3 chars among 8 in coalesce and 6 in decode) to write it in queries, but there is one thing you should keep in mind when using NVL.
First, let’s face the problem:
create package test_pck is
function get_user_id return number;
end;
/
create or replace package body test_pck is
function get_user_id return number
is
l_res number;
begin
<<lbl>>
if 1 < 2 then
goto lbl;
end if; end;
end;
/
Here we have created a package with a function that never returns a value, because it contains an infinity loop.
I picked this method for demonstration to be sure that examples will show you the same result despite IDE and environment settings you have.
So, let’s run this query:
select nvl(1, test_pck.get_user_id)
from dual
It has hung.
It tells us that the test_pck.get_user_id function was called despite the fact that the first parameter is 1, which is not null.
Generally, it’s not a problem. But it may be, if your second argument in nvl is a heavy function. In this case SQL query might work slower than you expect.
Do all functions that work with null values work the same? Let’s see:
COALESCE:
-- Lazy
select coalesce(1, test_pck.get_user_id)
from dual
DECODE:
-- Lazy
select decode(1, 1, 1, test_pck.get_user_id)
from dual
CASE:
-- Lazy
select case
when 1 = 1 then 1
else test_pck.get_user_id
end
from dual
We forgot about nvl’s brother - NVL2
-- Not Lazy
select nvl2(1, 2, test_pck.get_user_id)
from dual
Yes, it’s not lazy, like nvl.

I think it’s not a problem when you use nvl with “static” values. But if you use functions as one (or both) arguments to nvl, it’s better to replace it with a call to something lazier.

Summary: Typescript’s discriminated unions may be used to force you to handle exceptions.
If a function can throw an error, it should be wrapped in try/catch block to be properly handled.
However, error handling can be ignored, which adds more room for potential errors.
function getUserFromStorage(id: string) {
return undefined
}
function getUser(id: string) {
const user = getUserFromStorage(id)
if (user === undefined)
throw new Error('Specified user does not exist')
return user
}
function printUserInfo(id: string) {
const user = getUser(id)
console.log(`User name is ${user.name}`)
}
The problem here is that we didn’t check for errors when we retrieve user from our storage. Moreover, TS compiler don’t actually care.
Ideally, printUserInfo should handle possible errors:
function printUserInfo(id: string) {
try {
const user = getUser(id)
console.log(`User name is ${user.name}`)
}
catch {
console.error('Some error')
}
}
A union type is a type that combines multiple types into one. A variable of a union type can store only values with those types:
type mode = 'edit' | 'view' | number
// ok, type ='edit'
const a = 'edit'
// ok, type = number
const b = 24
// ok, type = 'view'
const c = 'view'
// type error: type string is unassignable to type mode
const d = 'randomstring'
When dealing with union types, we often need to narrow them before use:
type StringOrNumber = string | number
function getStringOrNumber(): StringOrNumber {
return 2
}
let v = getStringOrNumber()
// Error!
// The left-hand side of an arithmetic operation must be of
// type 'any', 'number', 'bigint' or an enum type.
console.log(v ** 3)
See, typescript complains because it doesn’t know whether v is string or number, Therefore, we need to make sure that v is a number:
type StringOrNumber = string | number
function getStringOrNumber(): StringOrNumber {
return 2
}
let v = getStringOrNumber()
if (typeof v === 'number')
console.log(v ** 3)
else
console.log(v.toLowerCase())
Take a look at the last example one more time; did you notice console.log(v.toLowerCase())?
It works because this statement is placed in the else branch of our check, so typescript knows that v is a string.
We can use union types and required type narrowing to make result checking mandatory - or our program won’t be compiled.
This is how it can be implemenented.
First of all, we create two main types and their union:
interface OkResult<T> {
ok: true
value: T
}
interface FailResult {
ok: false
error: string
}
type OkOrFail<T> = OkResult<T> | FailResult
Each of these types has ok field, which we can use to narrow OkOrFail type to OkResult or FailResult:
type User = {
name: string
email: string
}
function getUser(id: number): OkOrFail<User> {
try {
const user = getUserFromDb(id)
return {
ok: true,
value: user,
}
}
catch {
return {
ok: false,
error: 'can\'t find a user'
}
}
}
We used try/catch to return OkResult or FailResult, so our function doesn’t throw errors.
It returns union type instead, and in order to work with the returned error we need to narrow result to OkResult type:
const u = getUser(1)
// Type Error!
// If u is `FailResult`, it doesn't have the `value` field!
console.log(u.value)
// Now everything is ok, we narrow result down to `OkResult` type
if (u.ok)
console.log(u.value)
Always returning literal objects is too much to type, so we can create helper functions for this:
function ok<T>(value: T): OkResult<T> {
return {
ok: true,
value,
}
}
function fail(error: string): FailResult {
return {
ok: false,
error,
}
}
And then our getUser can be refactored:
function getUser(id: number): OkOrFail<User> {
try {
const user = getUserFromDb(id)
return ok(user)
}
catch {
return fail('can\'t find a user')
}
}
That’s it, I hope you liked this article, good luck!
In this article, we’ll implement our own signals.
Signals are objects that incapsulate access to their original value and track dependencies that use these signals.
The goal of this post is to have fun and to create the basic understanding through practice of how such things can work.
In vue3, there are two main reactivity primitives: ref and reactive. They’re not called signals in vue, but they’re the same. From the documentation:
Fundamentally, signals are the same kind of reactivity primitive as Vue refs. It’s a value container that provides dependency tracking on access, and side-effect triggering on mutation.
Vue automatically tracks dependencies that use refs or reactive objects, and triggers re-render or re-computation (if we talk about such thing as computed) when their value is changed.
Additionally, vue provides ‘watchers’(watch, watchEffect), which run callback functions any time their ‘watched’ value has been changed. In code it looks this way:
const name = ref('name')
watch(name, (newName) => {
console.log(newName)
})
In S.js, signals are created with the S.data function. To change the signal’s value, you call signal as a function with an argument, and you call signal without arguments to get its current value:
const name = S.data('Andrew')
name('Saphir')
console.log(name()) // prints 'Saphir'
S.js has the on method, which is identical to vue’s watch:
const counter = S.data(0)
S.on(counter, () => {
console.log('The counter has been changed')
})
Our signals will work as in the S.js library - createSignal() function will return a function that can be used as a setter when we provide a new value, and as a getter when called without arguments:
const userName = createSignal('User13')
console.log(userName()) // prints 'User13'
userName('User')
console.log(userName()) // prints 'User'
For simple values like strings or numbers changing values by simply passing them as arguments is ok, but for more complex types it may be too verbose. Imagine a user object with a complex structure like this:
const user = {
name: 'User13',
age: 44,
email: 'user13@mail.com',
created_at: '2024-01-01',
}
To update one property, we have to pass a new value to a signal:
const signal = createSignal(user)
signal({
name: 'User02',
age: 44,
email: 'user13@mail.com',
created_at: '2024-01-01',
})
console.log(signal().name) // 'User02'
We can, hovever, simplify this by using spread operator and signal as a getter:
const signal = createSignal(user)
signal({
...signal(), // Will return the current object
name: 'User02',
})
Looks better, yet we can make it better - pass a callback function with one parameter - current signal’s value, and assign result as a new value:
const signal = createSignal(user)
signal(u => ({
...u,
name: 'User02',
}))
Or with simple types:
const signal = createSignal(3)
signal(v => ++v)
console.log(signal()) // prints '4'
Signals as containers for values are not very useful, though. We want to be able to perform some actions when signal’s value changed. For this, we’ll create a function named on:
const s = createSignal(12)
on(s, (newVal) => {
console.log(`New value is ${newVal}`)
})
s(13)
s(v => v++)
What we expect from this code? It should print these two lines:
New value is 13
New value is 14
First thing that we’ll create is a function that acts differently depending whether it’s called with arguments or without them. For this, we need the arguments object.
function signal(param) {
if (arguments.length === 0)
console.log('Without arguments')
else
console.log('With arguments')
}
signal() // 'Without arguments'
signal(23) // 'With arguments'
Note that we can’t check param for undefined, because in this case we won’t be able to distinct signal() and signal(undefined) calls:
function signal(param) {
if (param === undefined)
console.log('Without arguments')
else
console.log('With arguments')
}
signal() // 'Without arguments'
signal(2) // 'With arguments'
// Oh no! It prints 'Without arguments'!
signal(undefined) // 'Without arguments'
createSignalFor keeping the same state between signal function calls we’ll wrap our state variable in a closure.
function createSignal(value) {
let _value = value
function signal(v) {
const isSetter = arguments.length > 0
if (isSetter) {
if (typeof v === 'function') {
_value = v(_value)
} else {
_value = v
}
} else {
return _value
}
}
return signal
}
const name = createSignal('Anna')
console.log(name()) // 'Anna'
console.log(name('Tanya'))
console.log(name()) // 'Tanya'
And that’s it, our signal is ready. It’s simple, but it works! And it also works with functions, as we planned:
const user = createSignal({ name: 'Anna', age: 41 })
user(u => ({...u, name: 'Tanya'}))
console.log(user().name) // 'Tanya'
console.log(user().age) // 41
on functionThis function takes a signal and a callback that should be executed when the signal is changed. At this point, we should think about few things:
Data structures go first. We’ll use Map with signals as its keys and array of callbacks as its values. It will allow us to quiclky find required callbacks. This map should be global for the whole module:
const effects = new Map()
function on(signal, cb) {
const signalEffects = effects.get(signal)
if (signalEffects) {
signalEffects.push(cb)
} else {
effects.set(signal, [cb])
}
}
Very simple, isn’t it? We just push the callback to the array of already existed callbacks if it exists. If not, we create a brand new array with just one value - our callback.
Finally, we need to find these callbacks and execute them in our signals. This is the code that implements it:
// Find registered callbacks
const signalEffects = effects.get(signal)
if (signalEffects) {
for (const cb of signalEffects) {
cb(newSignalValue)
}
}
I plan to write one more post which will introduce a few improvements to our current signals, so stay tuned in!
const effects = new Map()
function ss(value) {
let _value = value
function signal(v) {
const isSetter = arguments.length > 0
if (isSetter) {
if (typeof v === 'function') {
_value = v(_value)
} else {
_value = v
}
// Find registered callbacks
const signalEffects = effects.get(signal)
if (signalEffects) {
for (const cb of signalEffects) {
cb(_value)
}
}
} else {
return _value
}
}
return signal
}
function on(signal, cb) {
const signalEffects = effects.get(signal)
if (signalEffects) {
signalEffects.push(cb)
} else {
effects.set(signal, [cb])
}
}
For demonstration purposes, let’s create a simple web page with a button and a counter for the number of times the button was clicked.
<html>
<head>
<script type="text/javascript" src="index.js"></script>
<script type="text/javascript">
const counter = createSignal(0)
function onClick() {
counter(v => ++v)
}
window.addEventListener('load', () => {
const btn = document.querySelector('button')
// Display initial counter's value in the button
btn.innerText = counter()
// On each click, increment counter value
btn.addEventListener('click', onClick)
// Every time when the counter was changed,
// update button text with the new value
on(counter, (newValue) => {
btn.innerText = newValue
})
})
</script>
</head>
<body>
<button> </button>
</body>
</html>
Suppose you have Neovim and kickstart installed, you program in vue and typescript, and you want to have all these fancy features that volar offers.
In the ideal world, simply adding volar={} in LSP config should be enough, but starting from volar v 2.0 and higher, typescript support was moved to a separate package - @vue/typescript-plugin.
First of all, we need to install it globally:
npm i -g @vue/typescript-plugin
Then, open the init.lua file, find the code with local servers = {..} and make sure your tsserver config looks like this (add this section if it doesn’t exist):
tsserver = {
init_options = {
plugins = {
{
name = "@vue/typescript-plugin",
-- Exact location of the typescript plugin
location = "/usr/local/lib/node_modules/@vue/typescript-plugin",
languages = {"javascript", "typescript", "vue"},
},
},
},
-- Add TS support for vue files
filetypes = {'vue', 'javascript', 'typescript'}
}
You need to set the location of where the @vue/typescript-plugin is installed. To find out where is it, run this command:
npm root -g
This command prints the path to the directory where global packages are installed (on linux and mac, it’s usually /usr/local/lib/node_modules).
The last step - add the volar server:
local servers = {
tsserver = {...},
volar={}
-- You can also add additional useful
-- LSP servers, for example:
-- eslint = {}
-- tailwindcss = {}
}
That’s it, after restarting neovim, you’ll have the full experience of volar!
I’ve been an almost happy workflowy’s user for about a year, and as I wrote earlier , I’m done with workflowy. Yesterday, I read their privacy policy more carefully, and, you know, it’s full of gems, check it out:
Under the 2. Data that we use, receive, collect, process, share or store and how we may use it, they have a few nice points:
2.1.2. We might use, receive, collect, process or store Personal Data on potential customers, customers, employees, service providers, users of the Services and the Website, etc.
2.1.3.8. AS MOST OF THE DATA IS PROVIDED BY THE USER OF THE SERVICES WITHOUT OUR KNOWLEDGE, PROVIDE OTHER CATEGORIES OF PERSONAL DATA, SPECIFICALLY “SENSITIVE” AND “SPECIAL CATEGORIES OF DATA” (AS DEFINED BY GDPR i.e. medical data, financial data, political opinions, religious data, childrens’ data etc ) IS UNDER THE USER’S SOLE RESPONSIBILITY AND OWN RISK AND WE RECOMMEND NOT PROVIDING THIS TYPE OF DATA.
LOL, What kind of data I supposed to keep safe in Workflowy then?
And another one:
2.1.4.3. Internal business: We may use your Personal Data for internal business purposes, including, without limitation, to help us improve our Services, Website content and functionality, to better understand our customers and users, to protect against, identify or address wrongdoing, to enforce our contracts and this Privacy Policy, to provide you with customer service and to generally manage and operate our business (e.g., pay salaries and make considerations).
WTF is “Internal business purposes”, huh?
And this is for all users - even for those who have paid money. Oh my god, they suck so hard.
I know that almost all online web services have similar privacy policies, I just wrote about one of them.
Recently I was faced with a weird hugo behaviour on linux - it didn’t update the content of the site after running the dev server.
First thing that I tried is to run hugo with disabled “Fast Render Mode”:
hugo server --disableFastRender
And it didn’t help.
Solution: Reboot linux. I can’t find the link right now, but I found this answer somewhere on the internet. Turned out, it’s all because of suspend in linux - somehow the fact that I wasn’t shutting down a system relates to this issue.
Asciidoctor is a markup language, similar to markdown. One of its tools, asciidoctor-js (and most probably asciidoctor version written in Ruby), wraps every block (paragraphs, lists and so on) in a div. Resulting HTML is a mess.
For example, simple code listing is wrapped in three divs:
<div class="listingblock">
<div class="content">
<pre class="highlight"><code class="language-vue" data-lang="vue"><script setup lang='ts'>
import { useFocus } from '@vueuse/core'
</script></code></pre>
</div>
</div>
</div>Asciidoctor is a markup language similar to markdown, but more readable.
Asciidoctor has multiple “backends”, so you can choose from multiple options:
Run
npm i -g asciidoctor
Search for a package with name asciidoctor:
apt-get install asciidoctor
asciidoctor page.adoc -o page.html
Links are easy to remember, check it out:
This link is parsed automatically:
https://example.com
This link will render as a word 'link':
https://example.com[link]
If you want to open a link in a new tab:
https://example.com[window=_blank]
https://example.com[link^]
Mailto links are also automatically parsed:
mailto:username@example.com
mailto:username@example.com[email me]
Images.
Now you’ll never being thinking whether you wrote a link or an image element.
image::coolpic.png[]
image::coolpic.png[cool picture]
This example should give you the full understanding of the base elements in asciidoctor:
= Asciidoctor tutorial
Asciidoctor is a powerfull and elegand
markup language, much better than markdown.
It's strengths:
- Links
- Images
- Elegant headings syntax
== Text formatting
- **Bold text**
- __Italic text__
- +++Underlined text+++
== Blockquotes
Blockquotes are also better than in markdown:
----
This is a blockquote
----
Authoring is also supported:
[quote, proj11.com]
----
Asciidoctor as a **markup** language is better
than markdown, but its backends suck.
----
Very useful feature of Emacs: You can bookmark directories and files and switch between them quickly.
To add the current dired directory to bookmarks, press M-x r m in dired, then type bookmark name.
To add bookmark to a file, use the same keystroke in a window with a file.
To jump to a bookmark press M-x r l, move to required bookmark in the list and hit enter