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
386 karma · joined July 12, 2020
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
Seems like there is a bunch of interesting low level languages gaining steam at the moment.
Like defguard is_list_or_even_int(val) do is_list(val) or (is_integer(val) and val % 2 ==0) end
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
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`
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
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}
endSo 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
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
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
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. 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)
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 :/
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.
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
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)
[0] https://en.wikipedia.org/wiki/Negative_thermal_expansion
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.
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
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.
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.
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.