HackerTrans
トップ新着トレンドコメント過去質問紹介求人

akubera

no profile record

投稿

Guide to Timescript

jacquifashimpaur.com
1 ポイント·投稿者 akubera·3 年前·0 コメント

コメント

akubera
·12 か月前·議論
The smackbook pro! https://www.youtube.com/watch?v=6uvQTTPr9Rw
akubera
·12 か月前·議論
The PEP: https://peps.python.org/pep-0736/

The discussion: https://discuss.python.org/t/pep-736-keyword-argument-shorth...

The rejection: https://discuss.python.org/t/pep-736-shorthand-syntax-for-ke...

Grammar changes, in particular things used everywhere like function invocations, have to be worth paying the price for changing/adding new rules. The benefits of fewer characters and more explicit intention weren't enough to outweigh the costs.

There were other considerations: Do linters prefer one syntax to another? Does the name refer to the parameter or the argument in tooling? Should users feel pressure to name local variables the same as the function's parameters? What about more shorthand for common cases like func(x=self.x, y=self.y)?

I personally did not like the func(x=, y=) syntax. I think their example of Ruby's func(x:, y:) would actually make more sense, since it's syntax that would read less like "x equals nothing", and more "this is special syntax for passing arguments".
akubera
·昨年·議論
I'm reminded of the SMBC comic https://www.smbc-comics.com/?id=2722 which resonated with me. If it takes ~7 years to master something, you should dedicate yourself to becoming good at it. Or at least you don't have to tie your identity to what you do you right now; you can reinvent yourself and experience more from of life, but you have to give yourself the time to do so.

It's been almost 14 years since that was published, so maybe some self-reflection is due.
akubera
·昨年·議論
As others have said, Rust's ownership model prevents data races, as it can prove that references to mutable data can only be created if there are no other references to that data. Safe Rust also prevents use-after-free, double-free, and use-uninitialized errors. Does not prevent memory leaks or deadlocks.

It's easy to write code that deadlocks; make two shared pointers to the same mutex, then lock them both. This compiles without warnings:

    let mutex_a = Arc::new(Mutex::new(0_u32));
    let mutex_b = mutex_a.clone();
    
    let a = mutex_a.lock().unwrap();
    let b = mutex_b.lock().unwrap();
    println!("{}", *a + *b);
akubera
·2 年前·議論
Mathologer has a great video covering this: https://www.youtube.com/watch?v=aCj3qfQ68m0

Visualizes a proof and talks about special cases and a little of the history.
akubera
·2 年前·議論
In terms of the math: the table legs are assumed to be equal length, and the wobble is caused by variations of the surface. Specifically the feet of the table are in the same plane. So you could rotate your mathematical table until all feet are secure on the plane, then cut the legs to make the top flat again (legs will not be same length, but top and bottom remain planes).

As for @Cerium's real-life usage, you have possibility of uneven legs and uneven floor (and discontinuities, like a raised floorboard) so it's obviously not guaranteed, but if the floor is warped and smooth enough, you can try.

[EDIT]: Changed wording
akubera
·2 年前·議論
Looks good. One note about the video: you mention you recently watched a good video on 1-bit sound, and suggest it's worth a watch, but it doesn't appear to be linked-to in the description.
akubera
·2 年前·議論
What makes you think it's not compressed? (or that the data is stored as XML?)

There's very sophisticated compression systems throughout each experiment's data acquisition pipelines. For example this paper[1] describes the ALICE experiment's system for Run3, involving FPGAs and GPUs to be able to handle 3.5TB/s from all the detectors. This one [2] outlines how HL-LHC & CMS use neural networks to fine tune compression algorithms on a per-detector basis.

Not to mention your standard data files are ROOT TFiles with TTrees which store arrays of compressed objects.

It's all pretty neat.

[1] https://arxiv.org/pdf/2106.03636

[2] https://arxiv.org/pdf/2105.01683
akubera
·2 年前·議論
That seems to be the sentiment here. I'll take it into consideration. Thanks.
akubera
·2 年前·議論
For the Rust crate, there is already an arbitrary limit (defaults to 100 digits) for "unbounded operations" like square_root, inverting, division. That's a compile time constant. And there's a Context object for runtime-configuration you can set with a precision (stop after `prec` digits).

But for addition, the idea is to give the complete number if you do `a + b`, otherwise you could use the context to keep the numbers within your `ctx.add(a, b)`. But after the discussions here, maybe this is too unsafe... and it should use the default precision (or a slightly larger one) in the name of safety? With a compile time flag to disable it? hmm...
akubera
·2 年前·議論
I think that's the use-case for the rust_decimal crate, which is a 96-bit floating number (~28 decimal digits) which is safer and faster than the bigdecimal crate (which at its heart is a Vec<u64>, unbounded, and geared more for things like calculating sqrt(2) to 10000 places, that kind of thing). Still, people are using it for serialization, and I try to oblige.

Having user-set generic limits would be cool, and something I considered when const generics came out, but there's a lot more work to do on the basics, and I'm worried about making the interface too complicated. (And I don't want to reimplement everything.) D

I also would like a customizable parser struct, with things like localization, allowing grouping-delimiters and such (1_000_000 or 1'000'000 or 10,00,000). That could also return some kind of OutOfRange parsing error to disallow "suspicious" values, out of range. I'm not sure how that to make that generic with the serde parser, but I may some safe limits to the auto serialization code.

Especially with JSON, I'd expect there's only two kinds of numbers: normal "human" numbers, and exploit attempts.
akubera
·2 年前·議論
This isn't about parsing so much as letting the users do "dangerous" math operations. The obvious one is diving by zero, but when the library offers arbitrary precision, addition becomes dangerous with regard to allocating all the digits between a small and large value

  1e10 + 1e-10 = 10000000000.0000000001
  1e10000000000000000000 + 1e-10000000000000000000 = ...
It's tough to know where to draw the lines between "safety", "speed", and "functionality" for the user.

[EDIT]: Oh I see, fix the parser to disallow such large numbers from entering the system in the first place, then you don't have to worry about adding them together. Yeah that could be a good first step towards safety. Though, I don't know how to parametrize the serde call.
akubera
·2 年前·議論
I was attempting to solve this very problem in the Rust BigDecimal crate this weekend. Is it better to just let it crash with an out of memory error, or have a compile-time constant limit (I was thinking ~8 billion digits) and panic if any operation would exceed that limit with a more specific error-message (does that mean it's no longer arbitrary-precision?). Or keep some kind of overflow-state/nan, but then the complexity is shifted into checking for NaNs, which I've been trying to avoid.

Sounds like Haskell made the right call: put warnings in the docs and steer the user in the right direction. Keeps implementation simple and users in control.

To the point of the article, serde_json support is improving in the next version of BigDecimal, so you'll be able to decorate your BigDecimal fields and it'll parse numeric fields from the JSON source, rather than json -> f64 -> BigDecimal.

    #[derive(Serialize, Deserialize)]
    pub struct MyStruct {
      #[serde(with = "bigdecimal::serde::json_num")]
      value: BigDecimal,
    }
Whether or not this is a good idea is debatable[^], but it's certainly something people have been asking for.

[^] Is every part of your system, or your users' systems, going to parse with full precision?
akubera
·2 年前·議論
I'd bet they have very similar performance-metrics, but the yield syntax is more extensible (i.e. you're not limited to one expression) and debug-able (you can put breakpoints within the function).

Also the name and the generator is nicer (for some definition of nice):

   >>> def square_vals(x : list):
   ...    return (v * v for v in x)
   ... 
   >>> square_vals([1,2,3])
   <generator object square_vals.<locals>.<genexpr> at 0x786b8511f5e0>

   >>> def square_vals_yields(x: list):
   ...     for v in x:
   ...         yield v * v
   ... 
   >>> square_vals_yields([1,2,3])
   <generator object square_vals_yields at 0x786b851f5ff0>


I think it's more idiomatic to pass generator-comprehensions into functions rather than return them from functions

    >>> sum((v*v for v in x))
akubera
·3 年前·議論
I've had a similarly frustrating time trying to understand and wrangle the pyproject.toml builder system, (egg-layer? wheel-roller? cheese-monger?)

One thing the author might want to try is writing their own "build-backend". You can specify your own script (even use setup.py) and that will be the target of python -m build or pip wheel or presumably whatever build-frontend you use.

    # pyproject.toml
    [build-system]
    requires = ["setuptools"]
    build-backend = "setup"  # import setup.py as the build-module
    backend-path = ["."]

Then in setup.py you should write two functions:

    def build_sdist(sdist_directory, config_settings):
        ...

    def build_wheel(wheel_directory, config_settings, metadata_directory):
        ...

Where config_settings is a dictionary of the command line "--config-settings" options passed to the builder. (sys.argv does not have access to the actual invocation, I suppose to ensure frontend standardization)

example:

    $ python -m build --config-setting=foo=bar --config-setting=can-spam

    # will call 
    >>> build_sdist("the/dist/dir", {"foo": "bar", "can": "spam"})

Of course, you can extend the default setuptools build meta so you only have to do the pre-compilation or whatever your custom build step requires:

    from setuptools.build_meta import build_sdist as setuptools_build_sdist

    def build_sdist(sdist_directory, config_settings):
        # ... code-gen and copy files to source  ...

        # this will call setup.py::setup, to make things extra confusing
        return setuptools_build_sdist(sdist_directory, config_settings)
I had to create a temporary MANIFEST.in file to make sure that the setuptools build_sdist saw the generated files. Maybe there's a better way? I think the wheel "just" packages whatever the sdist produces, though that might be more difficult if you're compiling .so files or whatnot.

Still overall pretty fiddly/under-documented and a shame there seems to be a push for more dependencies rather than encouraging users to build their own solutions.

More info in PEP 517: https://peps.python.org/pep-0517/
akubera
·3 年前·議論
I think dekhn means the discussions and attempts at removing the GIL before this current PEP. Here's Guido's thoughts on it from 2007: https://www.artima.com/weblogs/viewpost.jsp?thread=214235 and that mentions a fork removing the GIL for Python 1.5 in 1999.
akubera
·8 年前·議論
If you use isinstance(x, (int, float)) instead of type(x) == int then I think you'll find your expected behavior.

When you say type narrowing do you mean floats should be automatically interpreted as int? There is typing.{SupportsInt, SupportsFloat} which can be considered "number" base classes which you may consider as type narrowing. Otherwise if you mean "type of x is known in this if-block" you do get that with `isinstance` type checks (which is the preferred, pythonic way).

I agree that mypy should warn if a NoReturn is assigned; apparently it just ignores typechecking below the NoReturn function call, and is really only used to ensure the NoReturn function is guaranteed to raise before it returns.