the crystal programming language always inlines blocks, which is great for performance but trades off space for speed. using blocks effectively means keeping this in mind.

somewhere along the line, i learned the habit of passing a block to a function as a means of customizing the behavior of the function. if the function that takes the block is large, it's important to remember that the body of the function is inlined where the function is called, which may not be what you are expecting. if you call the function multiple times, you even get multiple copies.

i just committed code that fixes an egregious example of this problem. in this case these ~30 lines of code replace the blocks with procs (which aren't inlined) and cut ~24mb (that's megabytes) off the executable (over a third of its size).

i regularly shoot myself in the foot trying to be clever, so i don' t know how prevalent this problem is in practice, but it's definitely something to keep in mind, especially if you see compile times and executable sizes growing!

#crystallang #ktistec

...well, for future reference, Invalid memory access (signal 11) at address 0x7ff7b19429f8 likely means the application has overrun its stack, especially if the stack trace shows even moderate recursion.

about the recursion though, this error happened after only 5 recursive calls (not 50,000) and that caught me off guard. i've been recently conditioned to think the stack only holds primitive values and references (pointers) but crystal, like c and similar languages, lets you pass around structures (instances of struct) by value and those values can be arbitrarily large.

now i need to figure out how to debug the contents of the stack...


til... the following works in #crystallang

[{1}, {2}, {3}].sort_by(&.first.-) # => [{3}, {2}, {1}]

because - is a method that returns the negative value of the number on which it is called. (the tuple in the example is obviously contrived...) this is in contrast to the following, which do the same thing but are more verbose:

puts [{1}, {2}, {3}].sort_by { |t| -t.first } 
puts [{1}, {2}, {3}].sort_by(&.first).reverse

one of the crystal programming language’s greatest strengths is the ease with which you can work with c apis and external libraries without leaving crystal. you can even implement callbacks in crystal!

in sqlite you can define new functions—callable from sql—with sqlite3_create_function by providing a name and a callback that implements the function. i created a new function called strip, entirely in crystal, that removes html markup and leaves text. it can be used in a sql query like so:

select * from objects
where strip(content) like "%term%"

it’s part of the recently released content filtering code.

#crystallang #ktistec