HNHacker News
TopNewBestAskShowJobs

el_oni

386 karma · joined July 12, 2020

Easily distracted and hardly motivated
submissionscomments
el_oni··on Update tinsel bunting
They have really great pensions and mat/paternity leave and those sorts of benefits.

You get some lifers that work there but they also get a lot of contractors and people that leave after a few years for a private sector job with more pay but worse pension.

Source: work as a contractor in UK public sector

el_oni··on Show HN: Error return traces for Go, inspired by Zig
Odinlang is a language in a similar space that seems to have first class support for matrix and vector operations. As well as having built in support for various graphics apps [0].

Seems like there is a bunch of interesting low level languages gaining steam at the moment.

[0] https://odin-lang.org/news/major-graphics-apis/

el_oni··on Elixir at Ramp
You can write custom guards out of any built in function that can already be used in a guard.

Like defguard is_list_or_even_int(val) do is_list(val) or (is_integer(val) and val % 2 ==0) end

el_oni··on Low current around roots boosts plant growth
tomatoes tend to lose flavour and texture if refigerated. but refrigeration tends to extend shelf life.

The other factor is that tomatoes that ripen on the vine tend to be tastier than tomatoes ripened off the vine. However fully ripe tomatoes tend to be squishier and don't travel as well. So they tend to be picked while firm and ripened using ethylene gas. These tend to be less tasty but easier to transport and store.

It's tradeoffs. A farmers market will typically have tastier tomatoes, when they are in season, than a supermarket, because they are picked when ripe, transported a short distance and sold within days. but if you're eating tomatoes out of season then expect them to be picked while unripe, refrigerated and then ripened off the vine so they can even make it to the supermarket shelves

el_oni··on How to cook ground meat perfectly without vision
I do this with bread baking, if it looks ready, temp it. If it's below ~90C i'll tent it with foil to stop the top from burning but let it get up to temp.
el_oni··on Unpacking Elixir: Syntax
the lsp (or maybe it's my editor) will also automatically do a closing `end` for every `do` similar to autobraces where typing an open `{` will automatically add a closing `}`

it means that most of the time i don't think about `end` unless it's an anonymous function `fn x -> x end`, which is where the only place i ever forget to add `end`

el_oni··on AOL pretends to be the internet
well this changes things. Thanks for the tip!
el_oni··on A Duodecade of Numberphile
That's not Brady, it's Mike
el_oni··on Most companies do not need Snowflake or Databricks
I begrudgingly agree. We tried to stand up a spark cluster and there are just loads of configuration and little niggles that just get in the way, like making sure everything on your cluster has the libraries they need.

Putting it on databricks most of those problems went away and we could just get in with writing the code.

Could we have figured out how to get spark working in a bespoke configuration? almost certainly. By our mid September deadline? Probably not

el_oni··on Railway Oriented Programming
Well, this isn't the only way to do things. There are exceptions in elixir and you can catch them if you want. But most functions that can fail have two versions

File.read() returns {:OK, contents} or {:error, reason}

So you can pattern match on the result.

File.read!() returns contents or raises an exception.

The first one allows you to use errors as values and handle the problem at the source. The latter assumes its going to be successful and either makes you catch the exception or, more likely for elixir, let the process crash.

The with statement is a good fit for certain domains where otherwise you might have a bunch of nested cases.

If you are worried about it returning a different type you can wrap it in the else block

    with {:ok, bar} <- func(foo)
    do
        bar
    else
        value -> {:failed, value}
end

So you can make your failed cases more homogeneous to pattern match on. You can even pattern match on the different failed cases if you want to ensure more homogeneity.

If using with doesn't make sense for the domain there are other constructs in the language that will

el_oni··on Railway Oriented Programming
In the examples yes, because it's just a simple binary ok or error case

but if you returned a list you can pattern match on an empty list, a single element list or a list that's longer. which you wouldn't do with exceptions in another language. that's the nice part about `with` that you can stop once you stop matching the pattern and return whatever you currently have, which in the list example may be a perfectly valid thing to return.

    with [value] <- Module.some_list_function(arg), # can return an empty list too
         [head | tail] = list <- Module.another_func(value), # can return a single element list
         longer_list <- Module.takes_multi_element_list(list)
    do
       longer_list
    end
There are loads of other examples for uses of this, or you can just write in an additional clause for your function that handles the other case and pipe it down the line.

It's about what makes sense for your domain.

I may not be explaining this well so apologies for any confusion

el_oni··on Railway Oriented Programming
The file handle is the PID of the process that opened the file, it monitors the process that asked for the file to be opened. and if that process goes down the file will be closed.

You can also add an else in the with so it looks like

    with {:ok, fh} <- File.open(filename),
         {:ok, contents} <- IO.read(fh)
    do
         contents
    else
         {:error, reason} -> File.close(fh)
                             {:error, reason} # this will return after the file has been closed
    end
or maybe you would prefer to open the file, and pass that into the with and either way close the file. I just used IO as an example because they return nice {:ok, x} or {:error, reason} tuples, but this works with any pattern.

The benefits over an exception is as the caller i can pattern match on the result of this. so i could have this is in a function in a case

    result = case with_example(filename) do
        {:ok, result} -> result
        {:error, :some_reason} -> # this is recoverable, do something else
             #log the issue
             recover!(filename) # bangs in functions indicate they can fail and raise an error
        {:error, :another_reason} -> # this is unrecoverable
              # log the issue
              
              raise "unrecoverable error"
        _ -> # any other case we don't know about
              raise "unexpected issue"

or i might not care and want it to crash if it doesn't match

{:ok, parsed} = with_example(filename) # will raise a match error if {:error, reason is returned

el_oni··on Railway Oriented Programming
The file handle is the PID of the process that opened the file, it monitors the process that asked for the file to be opened. and if that process goes down the file will be closed.

You can also add an else in the with so it looks like

    with {:ok, fh} <- File.open(filename),
         {:ok, contents} <- IO.read(fh)
    do
         contents
    else
         {:error, reason} -> File.close(fh)
                             {:error, reason} # this will return after the file has been closed
    end
or maybe you would prefer to open the file, and pass that into the with and either way close the file. I just used IO as an example because they return nice {:ok, x} or {:error, reason} tuples, but this works with any pattern.
el_oni··on Railway Oriented Programming
I really like things like this. There is a python talk called "so you want to be a python expert" and i think i watched it every 6 months for the first few years of my journey and each time i realised i got more and more of it. I'm sure if i were to watch it again there is probably still something now that i could get from it.
el_oni··on Railway Oriented Programming
Elixir has a nice take on this with the `with` keyword/macro

    with {:ok, file_handle} <- File.open(filename),

         {:ok, contents} <- IO.read(file_handle),

         {:ok, parsed} <- MyModule.parse(contents)

    do

       {:ok, parsed}

    end
what this does is run the functions in order top to bottom, and if the return value from each function doesn't match with what is on the left, it returns early with the thing that didn't match, otherwise it continues.

This means you don't need to write each function to take a tuple of {:ok, value} and another clause to take {:error, reason}, you can just write your functions to take the value they care about and let pattern matching in the with block to take care of error propagation.

so if File.open returns {:error, reason} then IO.read never executes and the result of the with is {:error, reason}

It essentially means you can program the happy path and let the caller match on the sad paths (if they want to)

el_oni··on If you succeed you will fail
I work better when I have a deadline, but i also expect my manager to allow for slippage if something is wrong with the product.

Currently we have an issue where we are telling the customer that we need a 4 week pilot to make sure that when real data comes in it behaves as we expect, and so we can get back to providers on how to fix their data. If you go live with only synthetic data ever going through your product then you are asking for trouble.

They are trying to negotiate that down to 2 weeks. Why? so their KPIs are met? Maybe it's because we are external, and if it fails they can blame us for the problem rather than them nickle and diming over a couple of weeks.

I want to consult in a different sector after this :/

el_oni··on Thoughts on Elixir, Phoenix and LiveView after 18 months of commercial use
Erlang and Elixir are what could be called pragmatic FP.

The idea is that your base abstraction should be functional, you can then have a genserver for that abstraction which is stateful.

So let's take lists for example. Building up a list is functional. But I could have a ListServer which takes an item and prepends it to a list. And just holds on to that. So lots of processes can send it messages to add things in, and order in the list is determined by order the messages arrived.

The way the server manages state is

State -> function -> State'

And those functions are easy to test.

It makes for a nice experience building software, the default is functional and you drop in processes which hold state when you need them. Compared to classes where the default is state.

el_oni··on A Critical Problem (2017)
We hate you when the bug reports roll in, but appreciate you when the product ships in a much cleaner state
el_oni··on Write Elixir NIFs in Rust
That is really neat!

I suppose the only downside of using the same code is it has the same bugs (e.g. I forgot to strip whitespace before doing a length check). So you don't get a belt and braces of having two lots of independently implemented validation

But then the upside is that it has the same bugs, so you only have to fix it once

el_oni··on Write Elixir NIFs in Rust
Another reason this is cool along with the other comment. Is that rustler will stop errors from crashing the BEAM.

If you implement a NIF in C and you panic then the erlang VM will crash bringing down everything.

If you do it in rustler then that panic is caught and is raised as an exception on the elixir side, which can be handled (or not) like any other exception.

This allows you safe bindings to existing rust libraries (such as polars in the case of explorer)

el_oni··on Some alloys don't change size when heated – recent work on why
There are some materials like this, it's called negative thermal expansion in materials science, the wikipedia page [0] on it has some examples of materials where this is the case.

[0] https://en.wikipedia.org/wiki/Negative_thermal_expansion

el_oni··on From Python to Elixir Machine Learning
Yes for polars in python. This was an issue I had with explorer in elixir. There is no elixir binding to the str.slice or str.extract functions yet
el_oni··on From Python to Elixir Machine Learning
Thanks José!

Yeah I noticed that, it looks like the numeric manipulations are well represented, less so for strings.

I'll dig out the the code later on and get an issue raised.

el_oni··on From Python to Elixir Machine Learning
I found explorer quite frustrating. I've used polars in python and loved it, but I brought in some financial data and couldn't strip off "£" from the start of a string so I could go on to cast it to a number.

As far as I could tell I would have to bring that data into elixir, do the text processing and put it back into explorer, which to me defeated the whole point of a dataframe library.

I imagine it's good for precleaned data, using it with the built in datasets has been fine

el_oni··on My PhD took a long time and there’s no shame in that
I worked in an office with about 8 other PhD students, was in a research group with another 10, and was friendly with another 10-15.

Social skills weren't lacking that much (don't get me wrong, we were a bunch of weirdos by some standards), but mental health certainly was.

There is a lot of pressure on PhD students and anxiety and/or depression affected all but a handful. Most people go into the programme wanting to be academics afterwards, so you look up to the academics that are there, listen to what they have to say. At the same time a whole lot of your ego is tied up into the success or failure of your work. If somebody shits on your work, that can break you.

I had therapy while in my final year, and so did a bunch of my peers, it's a meat grinder.

el_oni··on My PhD took a long time and there’s no shame in that
yeah, I finished mine in 2021. It took me 5 years (had a year off for extenuating circumstances) 3 years of lab work + 1 year off + 1 year writing up.

We didn't get any papers out during my actual time there, I wrote up a bunch of my results after i'd finished my viva and that got published in 2022 after I'd switched career tragecteries from science to software.

I'm incredibly lucky that my partner had a job that could make ends meet while writing up, and to find a company willing to take on a Chemistry PhD as a data engineer with no proven commercial experience.

My experience was a wild ride of high highs and crushing lows, I can't imagine doing that for over 7 years.

el_oni··on Adding Elixir to our Nextjs app (2022)
Which elixir repo? the elixir-lang repo last had a commit 3h ago. the phoenixframework repo was update last week
el_oni··on The note Reddit sent to moderators threatening them if they don’t reopen
What a bullshit take. Employees only tend to unionize when companies don't give a shit about them. Companies that treat employees like people and pay them fairly have much less to worry about
el_oni··on Scientists' report first X-ray of a single atom
My quick skim looks like its more like XPS or XAFS or XANES. Mixed with AFM
el_oni··on Could science leave the university?
I've commented on a similar topic before about knowing who the reviewers were based on their comments and papers they recomend we cited.

But as for the papers being inscruitable, i think part of that is just that the domain has it's own language, and assumed knowledge. I don't have to explain why i'm using the gibbs equation to calcualte free energy, or why i'm using hess's law. I just do it. The only things that need explaination are the novel applications of techniques.

When it comes to explaining those foundational concepts we need to pickup a text book or a popular science book. Speaking of, one of the things that makes me a little sad is how few popular science books there are around chemistry. There is loads about biology and physics, and even some around maths. Not a lot with chem.

← PreviousPage 2 of 6Next →